Leetcode学习计划-算法入门第12天
主题:动态规划
题目70:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
方案:发现规律,第 xx 级台阶的方案数是爬到第 x - 1台阶的方案数和爬到第 x - 2 级台阶的方案数的和。用动态规划法,先得出 转移方程公式:f(n)=f(n-1)+f(n-2),然后是 边界条件 f(0)=f(1)=1。
class Solution:
def climbStairs(self, n: int) -> int:
if n == 1 or n == 0:
return 1
a, b = 1, 1
for i in range(2, n + 1):
a, b = b, a + b
return b
题目198:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
方案:尝试使用递归的方法超出时间限制,因此改为动态规划的方法,确定转移方程为dp[i]=max(dp[i-2]+nums[i],dp[i-1]),确定边界条件数组长度为1时,只能取数组里的唯一值,当数组长度为2时取其中较大的值。
class Solution:
def rob(self, nums: List[int]) -> int:
size = len(nums)
if size == 0:
return 0
elif size == 1:
return nums[0]
dp = [0] * size
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, size):
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
return dp[len(nums) - 1]
优化,用滚动值代替动态数组:
class Solution:
def rob(self, nums: List[int]) -> int:
size = len(nums)
if size == 0:
return 0
elif size == 1:
return nums[0]
first, second = nums[0], max(nums[0], nums[1])
for i in range(2, size):
first, second = second, max(first + nums[i], second)
return second
题目120:给定一个三角形 triangle ,找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。
方案:注意到第i 行的元素个数也是i,因此只需长度为N的数组dp来动态规划即可,重点是建立行和行之间的转移方程,第i行从后向前更新dp值,最后取动态数组中的最小值即为所求。
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
size = len(triangle)
if size == 0:
return 0
elif size == 1:
return triangle[0][0]
dp = [0] * size
dp[0] = triangle[0][0]
for i in range(1, size):
dp[i] = dp[i - 1] + triangle[i][i]
for j in range(i - 1, 0, -1):
dp[j] = min(dp[j], dp[j - 1]) + triangle[i][j]
dp[0] = dp[0] + triangle[i][0]
return min(dp)
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。