力扣算法刷题Day48|动态规划:打家劫舍

力扣题目:#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] 在递归终止条件中已初始化
    • 确定遍历顺序:递归后序遍历树

你可能感兴趣的:(算法)