文章目录
- [1. 按摩师 (面试题17.16)](#1. 按摩师 (面试题17.16))
- [2. 打家劫舍II(LC 213)](#2. 打家劫舍II(LC 213))
- [3. 删除并获得点数(LC 740)](#3. 删除并获得点数(LC 740))
- [4. 粉刷房子(LCR091)](#4. 粉刷房子(LCR091))
1. 按摩师 (面试题17.16)
题目描述

解题思路
- 状态表示:到第
i个元素累计最长时间为dp[i]。对于每个元素都可以选择接受或不接受。需要两个数组来表示:f[i]表示接受当前预约的最长时间,g[i]表示不接受当前预约的最长时间 - 状态转移方程:
- 如果接受i预约,前一个一定不接受。
f[i] = g[i-1] + nums[i] - 如果不接受,前一个预约可能接受,也可能不接受。取最大值。
g[i] = max(f[i-1],g[i-1])

- 如果接受i预约,前一个一定不接受。
- 初始化:如果第一预约接受,
f[0] = nums[0];不接受则g[i] =0
代码实现
java
class Solution {
public int massage(int[] nums) {
int n = nums.length;
if(n==0)
return 0;
int[] f = new int[n];
int[] g = new int[n];
f[0] = nums[0];
for(int i = 1;i<n;i++){
f[i] = g[i-1]+nums[i];
g[i] = Math.max(f[i-1],g[i-1]);
}
return Math.max(f[n-1],g[n-1]);
}
}
2. 打家劫舍II(LC 213)
题目描述

解题思路
分类讨论,把环形问题转换为线性问题。
- 如果偷0号位置,则1号和n-号不可以偷,2号到n-2号可以偷,变成了上一题的解法
- 如果不偷0号位置,则1号到n-号可以偷。

代码实现
java
class Solution {
int[] nums;
public int rob(int[] _nums) {
nums = _nums;
int n = nums.length;
int case1 = rob1(2,n-2,n) + nums[0];
int case2 = rob1(1,n-1,n);
return Math.max(case1,case2);
}
int rob1(int l,int r,int n){
if(l>r)
return 0;
int[] f = new int[n];
int[] g = new int[n];
f[l] = nums[l];
for(int i = l;i<=r;i++){
f[i] = g[i-1]+nums[i];
g[i] = Math.max(f[i-1],g[i-1]);
}
return Math.max(f[r],g[r]);
}
}
3. 删除并获得点数(LC 740)
题目描述

解题思路
用数组hash记录每个数字出现的次数。这样就转换为第一个题,用两个数组表示当前数字删或不删得到的总和。
代码实现
java
class Solution {
public int deleteAndEarn(int[] nums) {
int[] hash = new int[10001];
int max = 0;
for(int num:nums){
hash[num]++;
max = Math.max(max,num);
}
int[] f = new int[max+1];
int[] g = new int[max+1];
g[1] = hash[1];
for(int i = 2;i<=max;i++){
f[i] = Math.max(g[i-1],f[i-1]);
g[i] =f[i-1] + hash[i]*i;
}
return Math.max(f[max],g[max]);
}
}
4. 粉刷房子(LCR091)
题目描述

解题思路
与第一题类似,只需要用三个数组做动态规划即可
代码实现
java
class Solution {
public int minCost(int[][] costs) {
int n = costs.length;
int[] red = new int[n];
int[] blue = new int[n];
int[] green = new int[n];
red[0] = costs[0][0];
blue[0] = costs[0][1];
green[0] = costs[0][2];
for(int i =1;i<n;i++){
red[i] = Math.min(green[i-1],blue[i-1])+costs[i][0];
blue[i] = Math.min(green[i-1],red[i-1])+costs[i][1];
green[i] = Math.min(red[i-1],blue[i-1])+costs[i][2];
}
return Math.min(green[n-1],Math.min(red[n-1],blue[n-1]));
}
}