डिवाइड और कॉनकॉर अल्गोरिथम और डायनामिक प्रोग्रामिंग अल्गोरिद्म में क्या अंतर है? दोनों शब्द कैसे अलग हैं? मुझे उनके बीच का अंतर समझ नहीं आ रहा है।
कृपया दोनों के बीच किसी भी अंतर को समझाने के लिए एक सरल उदाहरण लें और वे किस आधार पर समान दिखते हैं।
डिवाइड और कॉनकॉर अल्गोरिथम और डायनामिक प्रोग्रामिंग अल्गोरिद्म में क्या अंतर है? दोनों शब्द कैसे अलग हैं? मुझे उनके बीच का अंतर समझ नहीं आ रहा है।
कृपया दोनों के बीच किसी भी अंतर को समझाने के लिए एक सरल उदाहरण लें और वे किस आधार पर समान दिखते हैं।
जवाबों:
विभाजन और जीत
डिवाइड और कॉनकेयर समस्या को उप-समस्याओं में विभाजित करके काम करता है, प्रत्येक उप-समस्या को फिर से जीतता है और इन समाधानों को संयोजित करता है।
गतिशील प्रोग्रामिंग
डायनामिक प्रोग्रामिंग, अतिव्यापी उप-समस्याओं के साथ समस्याओं को हल करने की एक तकनीक है। प्रत्येक उप-समस्या को केवल एक बार हल किया जाता है और प्रत्येक उप-समस्या का परिणाम भविष्य के संदर्भों के लिए एक तालिका (आमतौर पर एक सरणी या हैश तालिका के रूप में लागू) में संग्रहीत किया जाता है। इन उप-समाधानों का उपयोग मूल समाधान प्राप्त करने के लिए किया जा सकता है और उप-समस्या समाधानों को संग्रहीत करने की तकनीक को संस्मरण के रूप में जाना जाता है।
आप सोच सकते हैं DP = recursion + re-use
अंतर को समझने के लिए एक क्लासिक उदाहरण इन दोनों दृष्टिकोणों को देखने के लिए होगा, जो एनएचआर नंबर प्राप्त करने की दिशा में है। इस सामग्री को MIT से जांचें ।
फूट डालो और जीतो दृष्टिकोण
डायनामिक प्रोग्रामिंग दृष्टिकोण
फूट डालो और जीतो और गतिशील प्रोग्रामिंग के बीच अन्य अंतर हो सकता है:
विभाजन और जीत:
गतिशील प्रोग्रामिंग:
कभी-कभी जब प्रोग्रामिंग पुनरावृत्ति होती है, तो आप फ़ंक्शन को एक ही पैरामीटर के साथ कई बार कॉल करते हैं जो कि अस्वाभाविक है।
प्रसिद्ध उदाहरण फाइबोनैचि संख्या:
index: 1,2,3,4,5,6...
Fibonacci number: 1,1,2,3,5,8...
function F(n) {
if (n < 3)
return 1
else
return F(n-1) + F(n-2)
}
चलो एफ (5) चलाएं:
F(5) = F(4) + F(3)
= {F(3)+F(2)} + {F(2)+F(1)}
= {[F(2)+F(1)]+1} + {1+1}
= 1+1+1+1+1
तो हमने कहा है: 1 बार एफ (4) 2 बार एफ (3) 3 बार एफ (2) 2 बार एफ (1)
डायनेमिक प्रोग्रामिंग अप्रोच: यदि आप एक ही पैरामीटर के साथ किसी फ़ंक्शन को एक से अधिक बार कॉल करते हैं, तो परिणाम को अगली बार सीधे एक्सेस करने के लिए एक चर में सहेजें। चलने का तरीका:
if (n==1 || n==2)
return 1
else
f1=1, f2=1
for i=3 to n
f = f1 + f2
f1 = f2
f2 = f
आइए फिर से F (5) पर कॉल करें:
fibo1 = 1
fibo2 = 1
fibo3 = (fibo1 + fibo2) = 1 + 1 = 2
fibo4 = (fibo2 + fibo3) = 1 + 2 = 3
fibo5 = (fibo3 + fibo4) = 2 + 3 = 5
जैसा कि आप देख सकते हैं, जब भी आपको कई कॉल की आवश्यकता होती है तो आप इसे पुनः प्राप्त करने के बजाय मूल्य प्राप्त करने के लिए संबंधित चर का उपयोग करते हैं।
वैसे, डायनेमिक प्रोग्रामिंग का मतलब पुनरावर्ती कोड को पुनरावृति कोड में बदलना नहीं है। यदि आप एक पुनरावर्ती कोड चाहते हैं, तो आप उप-वर्ग को एक चर में भी सहेज सकते हैं। इस मामले में तकनीक को संस्मरण कहा जाता है। हमारे उदाहरण के लिए यह इस तरह दिखता है:
// declare and initialize a dictionary
var dict = new Dictionary<int,int>();
for i=1 to n
dict[i] = -1
function F(n) {
if (n < 3)
return 1
else
{
if (dict[n] == -1)
dict[n] = F(n-1) + F(n-2)
return dict[n]
}
}
इसलिए डिवाइड एंड कॉनकेयर का संबंध यह है कि डी एंड डी एल्गोरिदम पुनरावृत्ति पर भरोसा करते हैं। और उनमें से कुछ संस्करणों में यह "एक ही पैरामीटर मुद्दे के साथ कई फ़ंक्शन कॉल है।" ऐसे उदाहरणों के लिए "मैट्रिक्स चेन गुणा" और "सबसे लंबे समय तक सामान्य अनुक्रिया" के लिए खोजें जहां डी एंड डी एल्गो के टी (एन) को बेहतर बनाने के लिए डीपी की आवश्यकता होती है।
जैसा कि मैंने इसे अभी के लिए देखा है मैं कह सकता हूं कि डायनेमिक प्रोग्रामिंग डिवाइड और विजय प्रतिमान का विस्तार है ।
मैं उन्हें पूरी तरह से अलग चीज नहीं मानूंगा। क्योंकि वे दोनों एक समस्या को दो या दो से अधिक एक ही या संबंधित प्रकार की उप-समस्याओं में तोड़-मरोड़ कर काम करते हैं , जब तक कि ये सीधे सरल नहीं हो जाते हैं। उप-समस्याओं का समाधान तब मूल समस्या का समाधान देने के लिए संयुक्त किया जाता है।
तो हमारे पास अभी भी अलग-अलग प्रतिमान क्यों हैं और मैंने डायनेमिक प्रोग्रामिंग को विस्तार क्यों कहा। ऐसा इसलिए है क्योंकि डायनेमिक प्रोग्रामिंग अप्रोच समस्या पर तभी लागू हो सकती है जब समस्या में कुछ प्रतिबंध या पूर्वापेक्षाएँ हों । और उसके बाद डायनामिक प्रोग्रामिंग मेमोइज़ेशन या टेबुलेशन तकनीक के साथ डिवाइड और विजय दृष्टिकोण को बढ़ाता है ।
चलो कदम से कदम…
जैसा कि हमने अभी पता लगाया है कि दो महत्वपूर्ण विशेषताएं हैं जो समस्या को विभाजित करने और जीतने के लिए गतिशील प्रोग्रामिंग के लिए लागू होना चाहिए:
इष्टतम उप -निर्माण - इष्टतम समाधान का निर्माण इसके उप-उत्पादों के इष्टतम समाधानों से किया जा सकता है
ओवरलैपिंग उप-समस्याओं - समस्या को उन सबप्रोब्लेम्स में तोड़ा जा सकता है जो कई बार पुन: उपयोग किए जाते हैं या समस्या के लिए एक पुनरावर्ती एल्गोरिथ्म एक ही उपप्रोब्लेम को हल करता है और हमेशा नए उपप्रक्रम उत्पन्न करता है
एक बार इन दो शर्तों को पूरा करने के बाद, हम कह सकते हैं कि डायनामिक प्रोग्रामिंग दृष्टिकोण का उपयोग करके इस विभाजन और जीत की समस्या को हल किया जा सकता है।
डायनेमिक प्रोग्रामिंग एप्रोच डिवाइड को बढ़ाता है और दो तकनीकों ( मेमोनाइजेशन और टेबुलेशन ) के साथ एप्रोच को जीतता है, जिसमें दोनों के पास उप-समस्याओं के समाधान को संग्रहीत करने और फिर से उपयोग करने का एक उद्देश्य है जो प्रदर्शन में काफी सुधार कर सकता है। उदाहरण के लिए, फिबोनाची फ़ंक्शन के भोले पुनरावर्ती कार्यान्वयन में समय की जटिलता है O(2^n)
जहां डीपी समाधान केवल O(n)
समय के साथ ही कर रहा है ।
संस्मरण (टॉप-डाउन कैश फिलिंग) पहले से गणना किए गए परिणामों को कैशिंग और पुन: उपयोग करने की तकनीक को संदर्भित करता है। इस fib
प्रकार याद किया गया कार्य इस प्रकार होगा:
memFib(n) {
if (mem[n] is undefined)
if (n < 2) result = n
else result = memFib(n-2) + memFib(n-1)
mem[n] = result
return mem[n]
}
टेबुलेशन (बॉटम-अप कैश फिलिंग) समान है, लेकिन कैश की प्रविष्टियों को भरने पर ध्यान केंद्रित करता है। कैश में मानों की गणना करना सबसे आसान है। सारणीकरण संस्करण fib
इस तरह दिखेगा:
tabFib(n) {
mem[0] = 0
mem[1] = 1
for i = 2...n
mem[i] = mem[i-2] + mem[i-1]
return mem[n]
}
आप यहाँ संस्मरण और सारणीकरण तुलना के बारे में अधिक पढ़ सकते हैं ।
मुख्य विचार जो आपको यहां समझाना चाहिए, वह यह है कि क्योंकि हमारी विभाजन और जीत की समस्या ने उप-समस्याओं को ओवरलैप कर दिया है, इसलिए उप-समस्या समाधान के कैशिंग संभव हो जाते हैं और इस प्रकार दृश्य पर संस्मरण / सारणीकरण कदम बढ़ जाता है।
चूंकि हम अब डीपी पूर्वापेक्षाओं और इसकी कार्यप्रणाली से परिचित हैं, इसलिए हम एक चित्र में ऊपर वर्णित सभी को डालने के लिए तैयार हैं।
यदि आप कोड उदाहरण देखना चाहते हैं, तो आप यहां अधिक विस्तृत विवरण देख सकते हैं, जहां आपको दो एल्गोरिथम उदाहरण मिलेंगे: बाइनरी सर्च और मिनिमम एडिट डिस्टेंस (लेवेंसहाइट डिस्टेंस) जो डीपी और डीसी के बीच के अंतर को दर्शा रहे हैं।
मुझे लगता है कि आप इस पर पहले ही विकिपीडिया और अन्य शैक्षणिक संसाधनों को पढ़ चुके हैं, इसलिए मैं उसमें से किसी भी जानकारी को पुनः प्राप्त नहीं करूंगा। मुझे यह भी कहना होगा कि मैं किसी भी तरह से एक कंप्यूटर विज्ञान विशेषज्ञ नहीं हूं, लेकिन मैं इन विषयों की मेरी समझ पर अपने दो सेंट साझा करूंगा ...
असतत उपप्रकारों में समस्या को तोड़ता है। फाइबोनैचि अनुक्रम के लिए पुनरावर्ती एल्गोरिथ्म डायनेमिक प्रोग्रामिंग का एक उदाहरण है, क्योंकि यह फ़ाइब (n-1) के लिए पहले हल करके फ़ाइब (n) के लिए हल करता है। मूल समस्या को हल करने के लिए, यह एक अलग समस्या हल करती है।
ये एल्गोरिदम आमतौर पर समस्या के समान टुकड़ों को हल करते हैं, और फिर उन्हें अंत में एक साथ रख देते हैं। मर्जेसर्ट फूट डालो और जीतो का एक उत्कृष्ट उदाहरण है। इस उदाहरण और फाइबोनैचि उदाहरण के बीच मुख्य अंतर यह है कि एक विलय में, विभाजन (सैद्धांतिक रूप से) मनमाना हो सकता है, और इससे कोई फर्क नहीं पड़ता कि आप इसे कैसे टुकड़ा करते हैं, आप अभी भी विलय और छंटनी कर रहे हैं। समान कार्य को सरणी को मर्ज करने के लिए करना पड़ता है, चाहे आप इसे कैसे भी विभाजित करें। फ़ॉइल (52) के लिए सॉल्यूशन के लिए फ़ाइब (2) को हल करने से अधिक चरणों की आवश्यकता होती है ।
मैं Divide & Conquer
एक पुनरावर्ती दृष्टिकोण और Dynamic Programming
तालिका भरने के रूप में सोचता हूं ।
उदाहरण के लिए, Merge Sort
एक Divide & Conquer
एल्गोरिथ्म है, जैसा कि प्रत्येक चरण में, आप सरणी को दो हिस्सों में विभाजित करते हैं, दो हिस्सों Merge Sort
पर पुन: कॉल करते हैं और फिर उन्हें मर्ज करते हैं।
Knapsack
एक Dynamic Programming
एल्गोरिथ्म है जैसा कि आप एक टेबल को भर रहे हैं, जिसमें समग्र समाधान के सबप्रोडेम्बल्स के लिए इष्टतम समाधान का प्रतिनिधित्व किया गया है। तालिका में प्रत्येक प्रविष्टि उस अधिकतम मूल्य से मेल खाती है जिसे आप 1-जे के दिए गए वेट डब्ल्यू के बैग में ले जा सकते हैं।
फूट डालो और जीतो में हर स्तर पर तीन चरण शामिल हैं:
डायनामिक प्रोग्रामिंग में निम्नलिखित चार चरण शामिल हैं:
1. इष्टतम समाधानों की संरचना की विशेषता ।
2. इष्टतम समाधानों के मूल्यों को पुन: परिभाषित करना।
3. इष्टतम समाधान के मूल्य की गणना करें।
4. कम्प्यूटेड जानकारी से एक इष्टतम समाधान का निर्माण ।
आसानी से समझने के लिए, एक तेज बल समाधान के रूप में विभाजित और जीतना और गतिशील प्रोग्रामिंग के रूप में इसके अनुकूलन की सुविधा देता है।
एनबी डिवाइड और ओवरलैपिंग सबप्रॉम्बल के साथ एल्गोरिदम को जीतना केवल डीपी के साथ अनुकूलित किया जा सकता है।
fact(5) = 5* fact(4) = 5 * (4 * fact(3))= 5 * 4 * (3 *fact(2))= 5 * 4 * 3 * 2 * (fact(1))
जैसा कि हम ऊपर देख सकते हैं, कोई भी तथ्य (x) दोहराया नहीं जाता है, तो इस तथ्य से कि गैर-अतिव्यापी समस्याएं हैं।
fib(5) = fib(4) + fib(3) = (fib(3)+fib(2)) + (fib(2)+fib(1))
जैसा कि हम ऊपर देख सकते हैं, फ़ाइब (4) और फ़ाइबर (3) दोनों फ़ाइबर (2) का उपयोग करते हैं। इसी तरह से कई फ़ाइब (x) बार-बार मिलते हैं। यही कारण है कि फाइबोनैचि ने उप-समस्याओं को ओवरलैप किया है।