174. 地下城游戏
本题是本人在学习动态规划遇到的第一道比较特殊的题目。
因为此题是倒着推的。因为要求最低血量,如果正着从起点开始求,不能保证后无效性。也就是说,前面的工作并没有解决子问题。
但是倒着推就能完美解决这个问题。
本题还有一个重要的点是,利用算术运算,负负得正,很便捷地解决了扣血的情况。
如果遇到加血的情况,此时就会出现血量为负数的情况,那么只需要将其更正为1即可。
因为是倒着推的,所以需要初始化重点,和最末行和最末列。
198. 打家劫舍
本题的特殊要求是得隔着取数字,所以就有两种情况,是否取当前数字。
ans[i] = Math.max(ans[i - 1]【取当前数字】, ans[i - 2] + nums[i - 1]【不取当前数字】)
初始化第零个房间为0元,第一个房间为第一件房间的金钱数。
337. 打家劫舍 III
本题作为二叉树情况下的隔着取数字。
我们需要设置两个HashMap,一个记录不取当前节点,另一个记录取出当前节点。键为当前节点,值为自此点而下的val之和。
f.put(root, root.val + g.getOrDefault(root.left, 0) + g.getOrDefault(root.right, 0));
如果取当前节点,则加入当前节点的值以及不取其左右子节点的函数值。
g.put(root, Math.max(f.getOrDefault(root.left, 0), g.getOrDefault(root.left, 0))+Math.max(f.getOrDefault(root.right, 0), g.getOrDefault(root.right, 0)));
如果不加入当前节点,则当前节点的值等于其左右子节点值得最大值。而其左右子节点又分为取与不取,再求取与不取得最大值。
674. 最长连续递增序列 & 300. 最长递增子序列
前者呢需要递增得字串连续,后者则不需要。
因为需要连续所以只有后者比前者大的时候才加一if(nums[i] > nums[i - 1]) {ans[i] = ans[i - 1] + 1;}
不需要连续呢,则需要从此处再次从前遍历,只要找到比当前小的数字就和当前答案进行比较迭代。
for(int j = 0; j < i; j++) {
if(nums[j] < nums[i]) {//以当前数字为结尾
ans[i] = Math.max(ans[i], ans[j] + 1);//持续更新ans[i]
}
}