Recursive understanding and time complexity calculation

1. Complexity analysis:

It can be understood that the depth of recursion is the space complexity, and the time complexity is O(T*depth), where T is the time complexity of each recursive function, and depth is the recursion depth.


#空间复杂度O(1)
def sum1_(n):
    res = 0
    for i in range(n+1):
        res+=i
    return res

#递归 空间复杂度O(n)
def sum2_(n):
    if n == 0:
        return 0
    return n+sum2_(n-1)

res1 = sum1_(n=10)
res2 = sum2_(n=10)
print('==res1:', res1)
print('==res2:', res2)

The time complexity of the above formula is also O(1*n)=O(n)

2. Examples

1.Calculate x^n:


def pow(x, n):
    if n==0:
        return 1.
    t = pow(x, n//2)
    if n%2:
        return x*t*t
    else:
        return t*t

res = pow(2,3)
print('res:', res)

Recursion depth: logn, the time complexity of each recursive function is O(1), so the time complexity is O(logn).

Space complexity: logn

2. If there are n steps, you can cross 1 step or 2 t steps each time . How many ways are there for n steps?

The first step is one step or the first step is two steps, and the next step is similar, so this is a recursion.

The n steps are the walking method of adding the remaining n-1 steps after walking one step, and the walking method of the remaining n-2 steps after walking two steps.

f(n)=f(n-1)+f(n-2)

Termination condition: There is only one step for one step, and only two steps for two steps.

f(1)=1,f(2)=2

def fun(n):
    if(n == 1): return 1

    elif (n == 2): return 2

    else:
        return fun(n - 1) + fun(n - 2)

The time complexity of each recursive function is O(1), and the space complexity: O(2^n), so the time complexity is O(2^n).

Disadvantages: stack overflow, repeated calculations, function call time-consuming, high space complexity, etc.

To prevent stack overflow caused by recursion, add depth, no more overflow if greater than 1000

depth=0
def fun(n):
    global depth
    depth+=1
    print('depth=',depth)
    if (depth>1000): return -1
    if(n == 1): return 1

    elif (n == 2): return 2

    else:
        return fun(n - 1) + fun(n - 2)
print(fun(3))

There are a lot of double calculations:

Optimization idea 1: 

Recursion, from bottom to top:

class Solution:
    def numWays(self, n: int) -> int:
        a,b=1,1
        for i in range(n):
            a,b = a+b,a
        return b

Idea 2: Store the calculated value for judgment:


def fun(n,arr):
    if(n == 1): return 1
    elif (n == 2): return 2
    else:
        if arr[n]!=-1:
            return arr[n]
        else:
            arr[n] = fun(n - 1,arr) + fun(n - 2,arr)
            return arr[n]
n = 6
arr = [-1]*(n+1)
res= fun(n=n, arr=arr)
print('==res:', res)

3. Recursively realize full arrangement:

def swap(a, p, i):
    a[p], a[i] = a[i], a[p]
    return a

#取第一个数,剩下的做排序,边界条件是开始索引p==终止索引q
def main(a, p, q):
    res = []

    def permute(a, p, q):
        if p == q:
            res.append(a.copy())
            print('res:', res)
        else:
            for i in range(p, q, 1):
                swap(a, p, i)
                permute(a, p+1, q)
                print('a:', a.copy())
                swap(a, p, i)#a还原成原顺序,比如2开头的结束了是2 1 3 需要还原成1 2 3 在吧3放在开头在排序
                print('==a:', a.copy())


    permute(a, p, q)
    print('==res:', res)


#
# a = [1]
# a = [1, 2]
a=[1, 2, 3]
main(a, 0, len(a))


class Solution:
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """

        def backtrack(first=0):
            # 所有数都填完了
            if first == n:
                res.append(nums.copy())
            for i in range(first, n):
                # 动态维护数组
                nums[first], nums[i] = nums[i], nums[first]
                # 继续递归填下一个数
                backtrack(first + 1)
                # 撤销操作
                nums[first], nums[i] = nums[i], nums[first]

        n = len(nums)
        res = []
        backtrack()
        return res


a = [1, 2, 3]
sol = Solution()
res = sol.permute(a)
print('===res:', res)

4. Recursively realize fast power

Question: Find the value of a modulo p to the power of b

#a^b%p
def a_b_p(a,b,p):
    if b == 0:
        return 1
    elif b%2 == 1:#b是奇数
        return a*a_b_p(a, b-1, p)%p
    else:#b是偶数
        temp = a_b_p(a, b//2, p)
        return (temp*temp)%p

res = a_b_p(3,3,4)
print('==res:', res)

5. Recursively implement Han Luo Tower


#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;
//a--from b--temp c--to
void hano(int n, char a, char b, char c);
int main(){
    hano(3, 'a', 'b', 'c');
    return 0;
    }
//a--from b--temp c--to
void hano(int n,char a, char b, char c){
    if(n==1){
        cout<<a<<"-->"<<c<<endl;
    }
    else{
        hano(n-1, a, c, b);//c为temp,a上面的n-1给b
        hano(1, a, b, c);//b为temp,a上面的1给c
        hano(n-1, b, a, c);//a为temp,b上面的n-1给c
    }
}

Add the plate number:

The plate is 1 to n from top to bottom

#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;
//a--from b--temp c--to
void hano(int top, int n, char a, char b, char c);
int main(){
    hano(1, 3, 'a', 'b', 'c');
    return 0;
    }
//a--from b--temp c--to
void hano(int top, int n,char a, char b, char c){
    if(n==1){
        cout<<"盘子"<<top<<a<<"-->"<<c<<endl;
    }
    else{
        hano(top, n-1, a, c, b);//c为temp,a上面的n-1给b
        hano(top + n - 1, 1, a, b, c);//b为temp,a上面的1给c
        hano(top, n-1, b, a, c);//a为temp,b上面的n-1给c
    }
}

Guess you like

Origin blog.csdn.net/fanzonghao/article/details/83038940