动态规划概念:
Programming - 在这里指用数学方法来根据子问题求解当前问题(通俗理解就是找到递推公式)
Dynamic - 指缓存上一步结果,根据上一步结果计算当前结果
简单理解:找出递推公式,将当前问题分解成子问题,分阶段进行求解。
求解过程中缓存子问题的解,避免重复计算。
例题:
分析:
这道题可以用动态规划的方式求解,我们先创建一个数组,数组的索引表示要偷的房间(例如1号房),数组中存放的每个元素代表偷到第几个房间能得到的最大价值。
每一行表示已经偷到第几个房子了,比如,只有0号房时,偷0号房,有两块。
有两个房子可偷时,我们可以放弃偷0号房,直接偷1号房,因为这样价值最大。
同样的,有3个房子可偷时,如果2号房价值加上0号房价值比1号房价值要大,那么应该放弃偷1号房,要偷0号和2号。偷到第几号房表示现在偷的最大价值,可能延用上一次的结果,并不一定代表这间房被偷了。
依次类推,这里不再赘述。
通过分析,得出下面的递推式:
代码实现:
/**
* 198. 打家劫舍
*/
public class HouseRobberLeetcode198 {
/*
房子价值 0(2) 1(7) 2(9) 3(3) 4(1)
0 1 2 3 4 编号
0 0 0 0 0
2 0 0 0 0
2 7 0 0 0
2 7 11 0 0
2 7 11 11 0
2 7 11 11 12
*/
public int rob(int[] nums) {
int len = nums.length;
if(len == 1){
return nums[0];
}
int[] dp = new int[len];
dp[0] = nums[0];
dp[1] = Integer.max(nums[0], nums[1]);
for (int i = 2; i < len; i++) {
dp[i] = Integer.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[len - 1];
}
public static void main(String[] args) {
HouseRobberLeetcode198 code = new HouseRobberLeetcode198();
System.out.println(code.rob(new int[]{2, 7, 9, 3, 1}));
System.out.println(code.rob(new int[]{2, 1, 1, 2}));
}
}