Is nested recursion possible or should recursion be avoided?

I faced such a question

  • F (1) = 1
  • F (2n) = F (n)
  • F (2n + 1) = F (n) + F (n + 1)

Design a recursive program to calculate F

Some users mentioned the use of two recursive function calls:

def calc(n):
  if n=1 :
    return 1
  else if(n%2)==0:
    return calc(n/2)
  else :
    return calc(n/2)+calc(n/2+1)  **NESTED RECURSION**

Is this the correct logic? Wouldn't the algorithm be exponentially large? I thought of simple code, for example:

def calc(count):
  result[1]=1
  n=2
  for range(1,count):
      if n%2=0:
          result.append(result[n])
      else :
          result.append(result[n/2]+result[n/2+1])
  return result
+3
source share
4 answers

Both of these approaches are correct. It is indeed legal to have several recursive calls from a function, and the point is that what you think is just one call, then the next, then the next, etc.

, , . , , () , . , :

T(1) = 1
T(2) = 1
T(n) <= T(n / 2) + T(n / 2 + 1) + 1

" ", , , .

, T (n) < = max {cn + d, a} c, d a. , T (n) = O (n) , , . ,

T(1) = 1
T(2) = 1

a = 1. . -, , (n/2) <= 2 (n/2 + 1) <= 2:

T(n) <= T(n / 2) + T(n / 2 + 1) + 1
     <= 1 + 1 + 1
     <= 3

, cn + d >= 3, n = 3 n = 4, . , , 3c + d >= 3 4c + d >= 3.

, , (n/2) <= 2 (n/2 + 1) >= 2. ,

T(n) <= T(n / 2) + T(n / 2 + 1) + 1
     <= 1 + max{c(n / 2 + 1) + d, 1} + 1
     <= 2 + max{c(n / 2 + 1) + d, 1}
     <= 3 + c(n / 2 + 1) + d

, 3 + c (n/2 + 1) + d <= cn + d, . , , n = 5, , ,

3 + c(n / 2 + 1) + d <= cn + d
3 + c(n / 2 + 1)     <= cn
3 + c(5 / 2 + 1)     <= 5c
3 + 5c/2 + c         <= 5c
3 + 7c/2             <= 5c
4                    <= 3c / 2
8 / 3                <= c

, , c >= 8/3.

, , , n/2, n/2 + 1 :

T(n) <= T(n / 2) + T(n / 2 + 1) + 1
     <= c(n / 2) + d + c(n / 2 + 1) + d + 1
     <= cn / 2 + cn / 2 + c + 2d + 1
      = cn + c + 2d + 1

, cn + d,

 cn + c + 2d + 1 <= cn + d
      c + 2d + 1 <=      d
      c +  d + 1 <= 0

, d = -c - 1.

, 3c + d >= 3, , 2c - 1 >= 3, 2c >= 4, c >= 2. , 4c + d >= 3, , c >= 2. c = 8/3, , d = -11/3,

T(n) <= max{8n/3 - 11/3, 1}

, T (n) = O (n), .


, , . - , .:-) , , . , O (n).

+9

. . (, ), ( ).

, , , . , .

, .

, . , .

+3

: , O (n) . , . !

Python 2.6.5 25 calc(1000), 80x calc(10000) 1712x calc(65535).

, , , 54613 = 1101010101010101 2. 16 .

calc(1000) 50 calc, calc(54613) 5166.

O (log n) :

def C(x):
    a = 1
    b = 0
    # Loop invariant: we are going to return a*C(x) + b*C(x + 1).
    while x >= 2:
        if x % 2 == 0:
            a += b
        else:
            b += a
        x //= 2
    return a + b

, .; -)

+3

, (O (log n)).

, n n + 1, [n/2] [n/2] +1.

, T (n) = (F (n), F (n + 1)), T ([n/2]) T (n).

,

Tuple F(int n) {
    // Base cases:

    Tuple result;
    if (n is even) {
        Tuple t = F(n/2);
        result.First = t.First;
        result.Second =t.First + t.Second;

        return result;
    }

    if (n is odd) {

        Tuple t = F((n-1)/2);
        result.First = t.First + t.Second;
        result.Second = t.Second;
        return result;
    } 
}

, , , O (logn).

Exercise . Give an O (log n) time algorithm for Fibonacci numbers using this trick.

Hint: use identifiers:

alt text

alt text

+3
source

Source: https://habr.com/ru/post/1786517/


All Articles