数据结构python实现(二)递归
(二)递归
- 什么样的问题能够用递归来解决
递归需要满足三个条件:
(1)一个问题的解可以分解成几个子问题的解
(2)这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
(3)存在递归终止条件
写递归代码的关键也是,找到递推公式和终止条件
- 案例
案例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)