leetcode 学习计划 动态规划第三天
1.打家劫舍
题目地址
这题第k家的最大值为(盗取第k-2的最大值+盗取第k家所得的钱) 和 (盗取第k-1家的最大值) 的最大值,动态转移方程如下
dp(k)=max(dp(k-1),dp(k-2)+nums[k]);
代码如下
public int rob(int[] nums) {
if (nums.length == 1) {
return nums[0];
}
int[] dp = new int[nums.length];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[nums.length - 1];
}
2.打家劫舍Ⅱ
题目地址
这题目和上一题的区别就是第一家和最后一家不能同时打劫。所以我们只要取从第0家打劫到第nums.length-1 和从第1家打劫到第nums.length 家的最大的值。
public int rob(int[] nums) {
if(nums.length==1){
return nums[0];
}
if(nums.length==2){
return Math.max(nums[0],nums[1]);
}
return Math.max(robtmp(nums,0,nums.length-2),robtmp(nums,1,nums.length-1));
}
public int robtmp(int[] nums,int start,int end) {
int a = nums[start];
int b = Math.max(nums[start], nums[start + 1]);
int temp;
for (int i = start + 2; i <= end; i++) {
temp = b;
b = Math.max(a + nums[i], b);
a = temp;
}
return b;
}
3.删除并获得点数
这题可以转化为第一题。当nums[i]看作新的数组的下标,所有等于nums[i]的和看作新数组的值,就转换为了第一题。
这里用下stream流,问就是看起来帅,但是实际速度比for循环低了很多,这点可以研究下,不过那次看strem流源码没怎么看懂,我还是太菜。
我们先求出新数组的长度,即元素组元素的最大值+1
Arrays.stream(nums).max().orElse(0) + 1
接着求出新数组的元素值
Arrays.stream(nums).forEach(num->sum[num]+=num), 此处sum就是新数组
public int deleteAndEarn(int[] nums) {
int[] sum = new int[Arrays.stream(nums).max().orElse(0) + 1];
Arrays.stream(nums).forEach(num->sum[num]+=num);
return rob(sum);
}
public int rob(int[] nums) {
int a = nums[0];
int b = Math.max(nums[0], nums[1]);
for (int i = 2; i < nums.length; i++) {
int temp = b;
b = Math.max(a + nums[i], b);
a = temp;
}
return b;
}