题目1. 最长递增序列-动态规划(即,找出一个给定序列中最长的递增序列?)
# 动态规划
'''
一般思路:
1. 穷举法/暴力搜索;
2. 记忆化搜索,剪枝
'''
# TODO 1. 暴力破解
def find_max_len1(nums, i):
'''
暴力破解:找出最长递增序列:
L(i) 从i开始的子序列长度:
L(0) -> L(1) -> L(2) -> L(3) -> L(4) # 最坏
L(1) -> L(2) -> L(3) -> L(4)
L(2) -> L(3) -> L(4)
L(3) -> L(4)
L(4)
:param nums:
:param i: 当前从第i个开始找
:return: 从i开始找的最大长度
'''
if i == len(nums) - 1:
return 1
max_len = 1
for j in range(i + 1, len(nums)):
if nums[i] < nums[j]:
# 最大长度 = max(当前最大长度, 后续最大长度(find_max_len(nums, j))和自身(1))
max_len = max(max_len, find_max_len1(nums, j) + 1)
return max_len
def length_of1(nums):
'''
遍历数组,找出从锁有i开始后的递增序列长度
:param nums:
:return:
'''
return max([find_max_len1(nums, i) for i in range(len(nums))])
# TODO 2. 暴力破解+剪枝
def find_max_len2(nums, i):
'''
避免重复节点的计算:找出最长递增序列:
动态规划就是通过避免重复节点的计算,加速计算的过程,用到字典或者哈希表保留计算的中间结果,也称为记忆化搜索。即空间换时间,带备忘录的递归,递归树的剪枝
:param nums:
:param i: 当前从第i个开始找
:return: 从i开始找的最大长度
'''
if i in memo:
return memo[i]
if i == len(nums) - 1:
return 1
max_len = 1
for j in range(i + 1, len(nums)):
if nums[i] < nums[j]:
# 最大长度 = max(当前最大长度, 后续最大长度(find_max_len(nums, j))和自身(1))
max_len = max(max_len, find_max_len2(nums, j) + 1)
memo[i] = max_len
return max_len
def length_of2(nums):
'''
遍历数组,找出从锁有i开始后的递增序列长度
:param nums:
:return:
'''
return max([find_max_len2(nums, i) for i in range(len(nums))])
# TODO 3. 动态规划
def length_of3(nums):
'''
动态规划: 从后往前算(这里的L是find_max_len函数)
L(0) = max(L(1), L(2), L(3), L(4)) + 1
L(1) = max(L(2), L(3), L(4)) + 1
L(2) = max(L(3), L(4)) + 1
L(3) = max(L(4)) + 1
L(4) = 1
:param nums:
:param i: 当前从第i个开始找
:return: 从i开始找的最大长度
'''
n = len(nums)
l = [1] * n
for i in reversed(range(n - 1)): # 3, 2, 1, 0
for j in range(i + 1, n):
# print(i, j)
if nums[j] > nums[i]:
l[i] = max(l[i], l[j] + 1)
# print(l)
return max(l)
if __name__ == '__main__':
x = [1, 5, 2, 4, 3]
memo = {}
print(length_of1(x))
print(length_of2(x))
print(length_of3(x))
题目2. 青蛙跳(可以跳1 2 级),问有多少跳的方案?
# 青蛙跳
'''
青蛙跳台阶:
首先,当只有一级台阶时,毫无疑问,只有一种跳法。其次,当有两级台阶时,就是两种跳法
那么,三级台阶时,应该两种情况
1、若青蛙先跳一级台阶,接下来就有两种跳法,要么一级一级地跳,要么直接就跳上两级
2. 若青蛙先跳两级台阶,接下来只能在再跳一级台阶(也可以先1后2)
所以当有三级台阶时,一共有3种跳法
那么,一共有4级台阶时,一共有多少种跳法呢?我们不妨列举一下
1.青蛙先跳一级台阶,接下来他就会还有3级台阶要去跳,而这3级台阶不就是上面3级台阶的重复吗!所以此时一共有3种跳法
2.青蛙先跳2级台阶,接下来他还有2级台阶要跳,此处也可以使用之前得出的2级台阶的结果,所以此时一共有2种跳法
所以当青蛙要跳4级台阶时,其实就是跳3级台阶的跳法加上跳2级台阶的跳法
总结:事实上,跳n级台阶的跳法就是跳n-1级台阶的跳法加上n跳-2级台阶的跳法,而这就可以使用递归的方法来解决
————————————————
版权声明:本文为CSDN博主「fiance111」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_60354608/article/details/123964767
'''
def jump_floor(n: int) -> int:
'''
递归做法
:param n:
:return:
'''
if n == 1:
return 1
elif n == 2:
return 2
else:
return jump_floor(n - 1) + jump_floor(n - 2)
def jump_floor_v1(n: int) -> int:
'''
动态规划版本:
eg: F(5) = F(4) + F(3)
F(4) = F(3) + F(2)
F(3) = F(2) + F(1) # 发现F(2)重复计算;
我们直接从后往前来
:param n:
:return:
'''
if n == 1:
return 1
elif n == 2:
return 2
dp = [1, 2] # n = 1, n = 2
for i in range(2, n):
dp.append(dp[i - 1] + dp[i - 2])
return dp[-1]
if __name__ == '__main__':
print(jump_floor(3))
print(jump_floor_v1(3))