数据结构python实现(二)递归

(二)递归

  1. 什么样的问题能够用递归来解决

递归需要满足三个条件:

(1)一个问题的解可以分解成几个子问题的解

(2)这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样	

(3)存在递归终止条件

写递归代码的关键也是,找到递推公式和终止条件

  1. 案例

案例1 阶乘

#循环实现
#时间O(n)
#空间O(1)
def factorial(n):
    result = 1
    for i in range(1, n+1):
        result *= i
    return result
  
#递归实现
#时间O(n)
#空间O(n)
ef factorial_recursive(n):
    if n == 1:
        return 1
    return n * factorial_recursive(n - 1)

案例2 斐波那契数列

#递归实现
#时间O(2^n)
def fibonacci1(n):
    assert(n>0)
    if (n <= 2): 
        return 1
    return fibonacci2(n-1) + fibonacci2(n-2)
  
  #循环实现
  #时间O(n)
  def fibonacci2(n):
    assert(n>0)
    a,b=0,1
    for i in range(1,n+1):
      a,b=b,a+b
    return a
  
  def fibonacci3(n):
    assert(n>0)
    if (n <= 1): 
        return (n,0)
    (a, b) = fibonacci3(n-1)
    return (a+b, a)

案例3 打印尺子

(热身)打印一下内容:

1

1 2 1

1 2 1 3 1 2 1

1 2 1 3 1 2 1 4 1 2 1 3 1 2 1

#时间O(2^n)
def ruler_bad(n):
    assert(n>=0)
    if (n==1):
        return "1"
    return ruler(n-1) + " " + str(n) + " " + ruler(n-1)

#时间O(n)
def ruler(n):
    assert(n>=0)
    if (n==1):
        return "1"
    t = ruler(n-1)
    return t + " " + str(n) + " " + t

#循环实现
def ruler2(n):
    result = ""
    for i in range(1, n+1):
        result = result + str(i) + " " + result
    return result

画尺子:

#画横线
def draw_line(tick_length, tick_label=''):
    line = '-' * tick_length
    if tick_label:
        line += ' ' + tick_label
    print(line)
#画每一个大格子    
def draw_interval(center_length):
    if center_length > 0:
        draw_interval(center_length - 1)
        draw_line(center_length)
        draw_interval(center_length - 1)
#画多个格子    
def draw_rule(num_inches, major_length):
    draw_line(major_length, '0')
    for j in range(1, 1 + num_inches):
        draw_interval(major_length - 1)
        draw_line(major_length, str(j))

案例4 数字表达式

Given two integers a ≤ b, write a program that transforms a into b by a minimum sequence of increment (add 1) and unfolding (multiply by 2) operations.

For example,

23 = ((5 * 2 + 1) * 2 + 1)

113 = ((((11 + 1) + 1) + 1) * 2 * 2 * 2 + 1)

def intSeq(a, b):
    if (a == b):
        return str(a)
    
    if (b % 2 == 1):
        return "(" + intSeq(a, b-1) + " + 1)"
    
    if (b < a * 2):
        return "(" + intSeq(a, b-1) + " + 1)"
        
    return intSeq(a, b/2) + " * 2";

案例5 汉诺塔

def hanoi(n, start, end, by):
    if (n==1):
        print("Move from " + start + " to " + end)
    else:
        hanoi(n-1, start, by, end)
        hanoi(1, start, end, by)
        hanoi(n-1, by, end, start)

格雷码

def moves_ins(n, forward):
    if n == 0:
        return
    moves_ins(n-1, True)
    print("enter ", n) if forward else print("exit  ", n)
    moves_ins(n-1, False)

案例6 subset

返回一个集合的所有子集

实现1:

def subsets(nums):
    result = [[]]
    for num in nums:
        for element in result[:]:
            x=element[:]
            x.append(num)
            result.append(x)
        
    return result

实现2(回溯):

def subsets_recursive(nums):
    lst = []
    result = []
    subsets_recursive_helper(result, lst, nums, 0);
    return result;

def subsets_recursive_helper(result, lst, nums, pos):
    result.append(lst[:])
    for i in range(pos, len(nums)):
        lst.append(nums[i]) #
        subsets_recursive_helper(result, lst, nums, i+1) #
        lst.pop()

案例7 subsets2

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

def subsets2(nums):
    res = [[]]
    for num in nums: 
        res += [ i + [num] for i in res if i + [num] not in res]
    return res

def subsets_recursive2(nums):
    lst = []
    result = []
    nums.sort()
    print(nums)
    subsets2_recursive_helper(result, lst, nums, 0);
    return result;

def subsets2_recursive_helper(result, lst, nums, pos):
    result.append(lst[:])
    for i in range(pos, len(nums)):
        if (i != pos and nums[i] == nums[i-1]):
            continue;
        
        lst.append(nums[i])
        subsets2_recursive_helper(result, lst, nums, i+1)
        lst.pop()

案例8 Permutation

Given abc:

Output: bca cba cab acb bac abc

def perm(result, nums):
    if (len(nums)==0):
        print(result)

    for i in range(len(nums)):
        perm(result+str(nums[i]), nums[0:i]+nums[i+1:])

案例9 Permutation Unique

def permUnique(result, nums):
    nums.sort()
    if (len(nums)==0):
        print(result)
    for i in range(len(nums)):
        if (i != 0 and nums[i] == nums[i-1]):
            continue;
        permUnique(result+str(nums[i]), nums[0:i]+nums[i+1:])
def permuteUnique(nums):
    ans = [[]]
    for n in nums:
        new_ans = []
        for l in ans:
            for i in range(len(l)+1):
                new_ans.append(l[:i]+[n]+l[i:])
                if i<len(l) and l[i]==n: break              #handles duplication
        ans = new_ans
    return ans

案例10 Permutation of Size K

takes two parameters n and k, and prints out all P(n, k) = n! / (n-k)! permutations that contain exactly k of the n elements. when k = 2 and n = 4

ab ac ad ba bc bd ca cb cd da db dc

def permSizeK(result, nums, k):
    if k == 0:
        print(result)
    for i in range(len(nums)):
        permSizeK(result+str(nums[i]), nums[0:i] + nums[i+1:], k - 1)

案例11 Letter Case Permutation

Enumerate all uppercase/lowercase permutation for any letter specified in input

For example,

word = “medium-one”Rule = “io”

solutions = [“medium-one”, “medIum-one”, “medium-One”, “medIum-One”]

results = set()
keys = set()

def permLetter(word, rule):
    rule = rule.lower()
    for c in rule:
        keys.add(c)
    permHelper(word, rule, 0, "")
    
def permHelper(word, rule, index, prefix):
    length = len(word)
    
    for i in range(index, length):
        c = word[i]
        if (c in keys):
            permHelper(word, rule, i + 1, prefix + c)
            
            c = c.upper()
            permHelper(word, rule, i + 1, prefix + c)
        else:
            prefix += c
    
    if (len(prefix) == len(word)):
        results.add(prefix)    

案例12 Combination Sum

Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

The same repeated number may be chosen from candidates unlimited number of times.

def comb(nums, t):
    result = []
    tmp = []
    combHelper(result, tmp, nums, t, 0)
    return result
        
def combHelper(result, tmp, nums, remains, start):
    if remains < 0: return
    if remains == 0:
        result.append(tmp[:])
    else:
        for i in range(start, len(nums)):
            tmp.append(nums[i])
            combHelper(result, tmp, nums, remains - nums[i], i)
            tmp.pop()

案例13 Combination Sum II

Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Note:

All numbers (including target) will be positive integers.

The solution set must not contain duplicate combinations.

def comb2(nums, t):
    result = []
    tmp = []
    nums.sort()
    combHelper2(result, tmp, nums, t, 0)
    return result
        
def combHelper2(result, tmp, nums, remains, start):
    if remains < 0: return
    if remains == 0:
        result.append(tmp[:])
    else:
        for i in range(start, len(nums)):
            if(i > start and nums[i] == nums[i-1]): continue; # skip duplicates
            tmp.append(nums[i])
            combHelper2(result, tmp, nums, remains - nums[i], i + 1)
            tmp.pop()

案例14 Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

def generateParenthesis(n):
    def generate(prefix, left, right, parens=[]):
        if right == 0:   parens.append(prefix)
        if left > 0:     generate(prefix + '(', left-1, right)
        if right > left: generate(prefix + ')', left, right-1)
        return parens
    return generate('', n, n)
posted @ 2020-05-28 23:18  sowhat1943  阅读(313)  评论(0编辑  收藏  举报