力扣题目:#198.打家劫舍
刷题时长:参考题解后5min
解题方法:动态规划
复杂度分析
问题总结
- 时间复杂度: O(n)
- 空间复杂度: O(n)
- 未考虑到边界情况,nums数组只有一个
- dp数组遍历时应从index2开始,不能覆盖初始化过的dp[0]和dp[1]
本题收获
- 动规思路
- 确定dp数组及下标的含义:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]
- 确定递推公式:dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
- dp数组的初始化:dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值
- 确定遍历顺序:从前到后
力扣题目:#213.打家劫舍II
刷题时长:参考题解后5min
解题方法:动态规划
复杂度分析
- 时间复杂度: O(n)
- 空间复杂度: O(n)
问题总结
- 分类讨论的思路不够合理
本题收获
- 分类讨论思路
- 情况一:考虑包含首元素,不包含尾元素
- 情况二:考虑包含尾元素,不包含首元素
- 两种情况取大的
- 动规思路同上#198.打家劫舍
力扣题目:#337.打家劫舍III
刷题时长:参考答案后5min
解题方法:动态规划
复杂度分析
- 时间复杂度:O(n),每个节点只遍历了一次
- 空间复杂度:O(log n),算上递推系统栈的空间
问题总结
- 未能想到如何定义dp数组,通过递归迭代来维护并更新长度为2的dp数组
本题收获
- 递归思路
- 参数:当前节点
- 返回值:dp数组
- 终止条件:空节点返回 (0, 0)
- 遍历顺序:后序
- 单层递归:
- 如果是偷当前节点,那么左右孩子就不能偷,val1 = root.val + left[0] + right[0]; (如果对下标含义不理解就再回顾一下dp数组的含义)
- 如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val0 = max(left[0], left[1]) + max(right[0], right[1])
- 最后当前节点的状态就是[val2, val1],即:[不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱]
- 动规思路
- 确定dp数组及下标的含义:本题dp数组就是一个长度为2的数组,在递归的过程中,系统栈会保存每一层递归的参数。下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。
- 确定递推公式:dp = [val0, val1]
- 不偷当前节点:val0 = max(left[0], left[1]) + max(right[0], right[1])
- 要偷当前节点:val1 = root.val + left[0] + right[0]
- dp数组的初始化:dp = [0, 0] 在递归终止条件中已初始化
- 确定遍历顺序:递归后序遍历树