पुनरावर्ती कार्यों के लिए जटिलता का निर्धारण (बिग ओ नोटेशन)


267

मेरे पास कल एक कंप्यूटर साइंस मिडटर्म है और मुझे इन पुनरावर्ती कार्यों की जटिलता को निर्धारित करने में सहायता की आवश्यकता है। मुझे पता है कि सरल मामलों को कैसे हल किया जाता है, लेकिन मैं अभी भी सीखने की कोशिश कर रहा हूं कि इन कठिन मामलों को कैसे हल किया जाए। ये केवल कुछ उदाहरण समस्याएं थीं जिनका मैं पता नहीं लगा सका। किसी भी मदद की बहुत सराहना की जाएगी और मेरी पढ़ाई में बहुत मदद मिलेगी, धन्यवाद!

int recursiveFun1(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun1(n-1);
}

int recursiveFun2(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun2(n-5);
}

int recursiveFun3(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun3(n/5);
}

void recursiveFun4(int n, int m, int o)
{
    if (n <= 0)
    {
        printf("%d, %d\n",m, o);
    }
    else
    {
        recursiveFun4(n-1, m+1, o);
        recursiveFun4(n-1, m, o+1);
    }
}

int recursiveFun5(int n)
{
    for (i = 0; i < n; i += 2) {
        // do something
    }

    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun5(n-5);
}

4
यदि आप हर बार विश्लेषण से नहीं गुजरना चाहते हैं, तो एक ब्लैक बॉक्स तकनीक है जिसे मास्टर विधि कहा जाता है। लेकिन इस धारणा के साथ कि इनपुट के सभी पुनरावर्ती विभाजन प्रत्येक उदाहरण में समान आकार के होते हैं।
विवेक कृष्ण


जवाबों:


345

बिग ओ नोटेशन में, प्रत्येक फ़ंक्शन के लिए समय जटिलता, संख्यात्मक क्रम में है:

  1. पहले मामले को बेस केस तक पहुंचने से पहले पुनरावर्ती रूप से n बार कहा जा रहा है O(n), इसलिए अक्सर इसे रैखिक कहा जाता है ।
  2. दूसरे फ़ंक्शन को प्रत्येक बार के लिए n-5 कहा जाता है, इसलिए हम फ़ंक्शन को कॉल करने से पहले n से पांच घटाते हैं, लेकिन n-5 भी है O(n)। (वास्तव में n / 5 बार का क्रम कहा जाता है। और, O (n / 5) = O (n))।
  3. यह फ़ंक्शन लॉग (n) बेस 5 है, हर बार जब हम फ़ंक्शन को कॉल करने से पहले 5 से विभाजित करते हैं तो इसका O(log(n))(बेस 5), जिसे अक्सर लॉगरिदमिक कहा जाता है और सबसे अधिक बार बिग ओ नोटेशन और जटिलता विश्लेषण बेस 2 का उपयोग करता है।
  4. चौथे में, यह O(2^n)या घातांक है , क्योंकि प्रत्येक फ़ंक्शन कॉल खुद को दो बार कॉल करता है जब तक कि इसे एन बार फिर से दर्ज नहीं किया गया हो ।
  5. अंतिम कार्य के लिए, लूप के लिए n / 2 लगता है क्योंकि हम 2 से बढ़ रहे हैं, और पुनरावर्तन n-5 लेते हैं और चूँकि लूप को पुनरावर्ती कहा जाता है इसलिए समय जटिलता (n-5) * (n) में है / 2) = (2n-10) * n = 2n ^ 2- 10n, एसिम्प्टोटिक व्यवहार और सबसे खराब स्थिति के कारण या ऊपरी सीमा जो कि बड़े हे के लिए प्रयास कर रही है, हम केवल सबसे बड़े कार्यकाल में रुचि रखते हैं O(n^2)

    शुभकामनाएँ आपके midterms पर;)


पांचवें के बारे में आपका अधिकार, n लूप के लिए कम हो जाएगा, लेकिन चौथे के लिए मुझे नहीं लगता कि इसके n ^ 2 को इसके पेड़ की तरह हर बार दो बार अपने कॉल को पुनरावृत्ति कहते हैं तो यह 2 ^ n प्लस होना चाहिए जो आपका था टिप्पणी में जवाब पहले।
कोडर

2
@MJGwater चलो चलन का समय m है। जब पुनरावर्ती 1 बार चलता है, तो यह लूप निष्पादित करने के लिए मी लेता है। जब पुनरावर्ती 2 बार चलती है, तो लूप को भी 2 बार चलाया जाता है, इसलिए इसे 2 मी ... और इसी तरह लगता है। तो यह '*' है, '^' नहीं।
bjc

3
@ कोड 5 के लिए स्पष्टीकरण अजीब लगता है। यदि लूप के n/2पुनरावृत्तियों में 2 परिणामों से वृद्धि होती है for, तो 5 से n/5घटकर पुनरावर्ती कॉल का परिणाम क्यों नहीं होगा ? यह अभी भी परिणाम होगा, O(n^2)लेकिन एक अधिक सहज स्पष्टीकरण की तरह लगता है। जब वे आवश्यक समान कार्य कर रहे हों तो घटाव और विभाजन को क्यों मिलाएं?
जैक

1
# कोड के लिए # 4, यदि फ़ंक्शन परिभाषा में 3 पुनरावर्ती कॉल थे, तो इसमें O (3 ^ n) की समय जटिलता होगी? और 5 पुनरावर्ती कॉल के लिए यह O (5 ^ n) होगा, सही है?
rmutalik

1
@ जेक हाँ, मैं भी यही सोच रहा था। यह n/5नहीं होना चाहिए n-5। और अंत में, पूरी तरह से उबाल जाएगा O(N^2)
अनुज

128

मामले के लिए जहां n <= 0, T(n) = O(1)। इसलिए, समय की जटिलता कब पर निर्भर करेगी n >= 0

हम नीचे n >= 0के भाग में मामले पर विचार करेंगे ।

1।

T(n) = a + T(n - 1)

जहां कुछ स्थिर है।

प्रेरण द्वारा:

T(n) = n * a + T(0) = n * a + b = O(n)

जहाँ a, b कुछ स्थिर हैं।

2।

T(n) = a + T(n - 5)

जहां कुछ स्थिर है

प्रेरण द्वारा:

T(n) = ceil(n / 5) * a + T(k) = ceil(n / 5) * a + b = O(n)

जहाँ a, b कुछ स्थिर और k <= 0 हैं

3।

T(n) = a + T(n / 5)

जहां कुछ स्थिर है

प्रेरण द्वारा:

T(n) = a * log5(n) + T(0) = a * log5(n) + b = O(log n)

जहाँ a, b कुछ स्थिर हैं

4।

T(n) = a + 2 * T(n - 1)

जहां कुछ स्थिर है

प्रेरण द्वारा:

T(n) = a + 2a + 4a + ... + 2^(n-1) * a + T(0) * 2^n 
     = a * 2^n - a + b * 2^n
     = (a + b) * 2^n - a
     = O(2 ^ n)

जहाँ a, b कुछ स्थिर हैं।

5।

T(n) = n / 2 + T(n - 5)

जहाँ n कुछ स्थिर है

फिर से n = 5q + rलिखें जहां q और r पूर्णांक और r = 0, 1, 2, 3, 4 हैं

T(5q + r) = (5q + r) / 2 + T(5 * (q - 1) + r)

हमारे पास है q = (n - r) / 5, और r <5 से, हम इसे एक स्थिर मान सकते हैं, इसलिएq = O(n)

प्रेरण द्वारा:

T(n) = T(5q + r)
     = (5q + r) / 2 + (5 * (q - 1) + r) / 2 + ... + r / 2 +  T(r)
     = 5 / 2 * (q + (q - 1) + ... + 1) +  1 / 2 * (q + 1) * r + T(r)
     = 5 / 4 * (q + 1) * q + 1 / 2 * (q + 1) * r + T(r)
     = 5 / 4 * q^2 + 5 / 4 * q + 1 / 2 * q * r + 1 / 2 * r + T(r)

R <4 के बाद से, हम कुछ निरंतर बी पा सकते हैं ताकि b >= T(r)

T(n) = T(5q + r)
     = 5 / 2 * q^2 + (5 / 4 + 1 / 2 * r) * q + 1 / 2 * r + b
     = 5 / 2 * O(n ^ 2) + (5 / 4 + 1 / 2 * r) * O(n) + 1 / 2 * r + b
     = O(n ^ 2)

1
मैंने हाल ही में एक साक्षात्कार प्रश्न (और साक्षात्कार का विस्तार करके) को विफल कर दिया है, जो कि एक पुनरावर्ती दूत समारोह के समय और स्थान की जटिलता का विश्लेषण करना है। यह उत्तर महाकाव्य है और इसने बहुत मदद की, मुझे इससे प्यार है, काश मैं आपको दो बार वोट दे पाता। मुझे पता है कि यह पुराना है, लेकिन क्या आपके पास अंतरिक्ष की गणना के लिए कुछ समान है - शायद एक लिंक, कुछ भी?
दिमित्र दिमित्रोव

नंबर 4 के लिए, भले ही परिणाम समान हो, लेकिन क्या इंडक्शन निम्नलिखित नहीं होना चाहिए? T (n) = a + 2T (n-1) = a + 2a + 4T (n-1) = 3a + 4a + 8T (n-1) = a * (2 ^ n - 1) + 2 ^ n * T (0) = a * (2 ^ n - 1) + b * 2 ^ n = (a + b) * 2 ^ n - a = O (2 ^ n)
स्नोफिश

27

पुनरावर्ती एल्गोरिथ्म की जटिलता का अनुमान लगाने के लिए सबसे अच्छे तरीकों में से एक मैं पुनरावर्ती पेड़ को आकर्षित कर रहा हूं। एक बार आपके पास पुनरावर्ती वृक्ष है:

Complexity = length of tree from root node to leaf node * number of leaf nodes
  1. पहले फ़ंक्शन की लंबाई nऔर पत्ती नोड की संख्या 1होगी इसलिए जटिलता होगीn*1 = n
  2. दूसरे फ़ंक्शन की लंबाई n/5और फिर से पत्ती नोड्स की संख्या 1होगी, इसलिए जटिलता होगी n/5 * 1 = n/5। इसका अनुमान लगाना चाहिएn

  3. तीसरे फ़ंक्शन के लिए, चूंकि nप्रत्येक पुनरावर्ती कॉल पर 5 से विभाजित किया जा रहा है, पुनरावर्ती पेड़ की लंबाई होगी log(n)(base 5), और पत्ती नोड्स की संख्या फिर से 1 ताकि जटिलता होगीlog(n)(base 5) * 1 = log(n)(base 5)

  4. चौथे फ़ंक्शन के लिए चूंकि प्रत्येक नोड में दो बाल नोड होंगे, पत्ती नोड्स की संख्या बराबर होगी (2^n)और पुनरावर्ती पेड़ की लंबाई nइतनी जटिल होगी (2^n) * n। लेकिन चूँकि nइसके सामने महत्वहीन है (2^n), इसलिए इसे नजरअंदाज किया जा सकता है और जटिलता को ही कहा जा सकता है (2^n)

  5. पांचवें समारोह के लिए, जटिलता को पेश करने वाले दो तत्व हैं। फ़ंक्शन की पुनरावर्ती प्रकृति और forप्रत्येक फ़ंक्शन में लूप द्वारा शुरू की गई जटिलता द्वारा पेश की गई जटिलता । उपरोक्त गणना करते हुए, फ़ंक्शन की पुनरावर्ती प्रकृति द्वारा शुरू की गई ~ nजटिलता और लूप के कारण जटिलता होगी n। कुल जटिलता होगी n*n

नोट: यह जटिलता का एक त्वरित और गंदा तरीका है (आधिकारिक कुछ भी नहीं!)। इस पर प्रतिक्रिया सुनना पसंद करेंगे। धन्यवाद।


बहुत बढ़िया जवाब! चौथे समारोह पर मेरा एक प्रश्न है। यदि इसमें तीन पुनरावर्ती कॉल होते, तो उत्तर होगा (3 ^ n)। या आप अभी भी कहेंगे (2 ^ n)?
बेन फोर्स्रुप

@ शुभम: # 4 मुझे सही नहीं लगता। यदि पत्तियों की संख्या है 2^nतो पेड़ की ऊंचाई होनी चाहिए n, नहीं log n। ऊंचाई केवल तभी होगी log nजब nपेड़ में कुल नोड्स का प्रतिनिधित्व किया जाए । लेकिन यह नहीं है।
जूलियन ए।

@BenForsrup: यह 3 ^ n होगा क्योंकि प्रत्येक नोड में तीन बच्चे नोड होंगे। इस बारे में सुनिश्चित करने का सबसे अच्छा तरीका यह है कि आप अपने आप को डमी मूल्यों के साथ पुनरावर्ती वृक्ष आकर्षित करें।
शुभम

# 2 को n-5 नहीं n / 5 होना चाहिए
फिन्तासीस

7

हम इसे गणितीय रूप से साबित कर सकते हैं कि कुछ ऐसा है जो मैं उपरोक्त उत्तरों में याद कर रहा था।

यह किसी भी विधि की गणना करने के तरीके को समझने में नाटकीय रूप से आपकी मदद कर सकता है। मैं इसे पूरी तरह से समझने के लिए ऊपर से नीचे तक पढ़ने की सलाह देता हूं कि यह कैसे करना है:

  1. T(n) = T(n-1) + 1इसका मतलब यह है कि विधि को समाप्त करने में लगने वाला समय उसी विधि के बराबर है लेकिन n-1 के साथ जो है T(n-1)और हम अब जोड़ते हैं + 1क्योंकि यह सामान्य ऑपरेशनों को पूरा होने (छोड़कर T(n-1)) में लगने वाला समय है । अब, हम T(n-1)अनुसरण के रूप में खोजने जा रहे हैं T(n-1) = T(n-1-1) + 1:। ऐसा लगता है कि अब हम एक ऐसा फंक्शन बना सकते हैं जो हमें किसी प्रकार की पुनरावृत्ति दे सकता है ताकि हम पूरी तरह से समझ सकें। हम के दाईं ओर स्थापित करेंगे T(n-1) = ...बजाय T(n-1)विधि के अंदर T(n) = ...: जो हमें दे देंगे T(n) = T(n-1-1) + 1 + 1है जो T(n) = T(n-2) + 2या दूसरे शब्दों में हम अपने लापता खोजने की जरूरत में k: T(n) = T(n-k) + k। अगला कदम यह है n-kकि वह दावा करे और दावा करे n-k = 1क्योंकि पुनरावृत्ति के अंत में जब ओ (1) होगा तो वह ठीक होगाn<=0। इस सरल समीकरण से अब हम जानते हैं कि k = n - 1। आइए हम kअपनी अंतिम विधि में जगह दें : T(n) = T(n-k) + kजो हमें देगा: T(n) = 1 + n - 1जो कि वास्तव में है nया O(n)
  2. 1 के समान है। आप इसे अपने स्वयं का परीक्षण कर सकते हैं और देख सकते हैं कि आपको मिलता है O(n)
  3. T(n) = T(n/5) + 1पहले की तरह, इस पद्धति को समाप्त करने का समय उसी पद्धति के समय के बराबर है, लेकिन n/5जिसके साथ यह बाध्य है T(n/5)। आइए T(n/5)1 में खोजें: T(n/5) = T(n/5/5) + 1जो है T(n/5) = T(n/5^2) + 1। चलो अंतिम गणना के लिए T(n/5)अंदर रखें :। फिर से पहले की तरह, जो कि यह पूछ रहा है कि 5 की शक्ति क्या है, हमें n देगा, इसका उत्तर है (आधार 5 का लॉग)। आइए हमारे निष्कर्षों को इस प्रकार रखें: जो हैT(n)T(n) = T(n/5^k) + kn/5^k = 1n = 5^klog5n = kT(n) = T(n/5^k) + kT(n) = 1 + lognO(logn)
  4. T(n) = 2T(n-1) + 1हमारे पास जो कुछ है वह मूल रूप से पहले जैसा है लेकिन इस बार हम विधि को 2 बार पुन: लागू कर रहे हैं इस प्रकार हम इसे 2 से गुणा करते हैं। आइए जानें वह T(n-1) = 2T(n-1-1) + 1कौन सा है T(n-1) = 2T(n-2) + 1। पहले की तरह हमारा अगला स्थान, हम अपनी खोज को जगह दें: T(n) = 2(2T(n-2)) + 1 + 1जो T(n) = 2^2T(n-2) + 2कि हमें देता है T(n) = 2^kT(n-k) + k। आइए kदावा करते हैं कि n-k = 1जो है k = n - 1। चलो kअनुसरण के रूप में रखें: T(n) = 2^(n-1) + n - 1जो मोटे तौर पर हैO(2^n)
  5. T(n) = T(n-5) + n + 1यह लगभग 4 के समान है लेकिन अब हम जोड़ते हैं nक्योंकि हमारे पास एक forलूप है। आइए जानें T(n-5) = T(n-5-5) + n + 1कौन सी है T(n-5) = T(n - 2*5) + n + 1। चलो इसे जगह देते हैं: T(n) = T(n-2*5) + n + n + 1 + 1)जो कि T(n) = T(n-2*5) + 2n + 2)और कश्मीर के लिए है: T(n) = T(n-k*5) + kn + k)फिर से: n-5k = 1जो n = 5k + 1कि लगभग है n = k। यह हमें देगा: T(n) = T(0) + n^2 + nजो मोटे तौर पर है O(n^2)

मैं अब बाकी उत्तरों को पढ़ने की सलाह देता हूं, जो अब आपको एक बेहतर परिप्रेक्ष्य प्रदान करेंगे। सौभाग्य उन बड़े हे जीत :)


1

यहां कुंजी कॉल ट्री की कल्पना करना है। एक बार ऐसा करने के बाद, जटिलता है:

nodes of the call tree * complexity of other code in the function

उत्तरार्द्ध शब्द की गणना उसी तरह की जा सकती है जैसे हम एक सामान्य पुनरावृत्ति कार्य के लिए करते हैं।

इसके बजाय, एक पूर्ण पेड़ के कुल नोड्स की गणना की जाती है

                  C^L - 1
                  -------  , when C>1
               /   C - 1
              /
 # of nodes =
              \    
               \ 
                  L        , when C=1

जहाँ C प्रत्येक नोड के बच्चों की संख्या है और L पेड़ के स्तर (रूट शामिल) की संख्या है।

पेड़ की कल्पना करना आसान है। पहले कॉल (रूट नोड) से शुरू करें फिर फ़ंक्शन में पुनरावर्ती कॉल की संख्या के समान बच्चों को आकर्षित करें। उप-कॉल में दिए गए पैरामीटर को "नोड के मूल्य" के रूप में लिखना भी उपयोगी है।

तो, ऊपर दिए गए उदाहरणों में:

  1. कॉल ट्री यहां C = 1, L = n + 1 है। बाकी फ़ंक्शन की जटिलता हे (1) है। इसलिए कुल जटिलता L * O (1) = (n + 1) * O (1) = O (n) है
n     level 1
n-1   level 2
n-2   level 3
n-3   level 4
... ~ n levels -> L = n
  1. यहां कॉल ट्री C = 1, L = n / 5 है। बाकी फ़ंक्शन की जटिलता हे (1) है। इसलिए कुल जटिलता L * O (1) = (n / 5) * O (1) = O (n) है
n
n-5
n-10
n-15
... ~ n/5 levels -> L = n/5
  1. यहाँ कॉल ट्री C = 1, L = log (n) है। बाकी फ़ंक्शन की जटिलता हे (1) है। इसलिए कुल जटिलता L * O (1) = log5 (n) * O (1) = O (लॉग (n)) है
n
n/5
n/5^2
n/5^3
... ~ log5(n) levels -> L = log5(n)
  1. कॉल ट्री यहां C = 2, L = n है। बाकी फ़ंक्शन की जटिलता हे (1) है। इस बार हम कॉल ट्री में नोड्स की संख्या के लिए पूर्ण सूत्र का उपयोग करते हैं क्योंकि C> 1. इसलिए कुल जटिलता है (C ^ L-1) / (C-1) * O (1) = (2 ^ n - 1 ) * O (1) = O (2 ^ n)
               n                   level 1
      n-1             n-1          level 2
  n-2     n-2     n-2     n-2      ...
n-3 n-3 n-3 n-3 n-3 n-3 n-3 n-3    ...     
              ...                ~ n levels -> L = n
  1. यहां कॉल ट्री C = 1, L = n / 5 है। बाकी फ़ंक्शन की जटिलता हे (एन)। इसलिए कुल जटिलता L * O (1) = (n / 5) * O (n) = O (n ^ 2) है
n
n-5
n-10
n-15
... ~ n/5 levels -> L = n/5
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.