[LC 动态规划]
70、爬楼梯
题目描述:有 N 阶楼梯,每次可以上一阶或者两阶,求有多少种上楼梯的方法。
定义一个数组dp储存上楼梯的方法数,dp[i]表示走到第i个楼梯的方法数。
第i个楼梯可以和从第i-1和i-2个楼梯再走一步到达,走到第i个楼梯的方法数为走到第i-1和第i-2个楼梯的方法数之和。
考虑到dp[i]只与dp[i-1]和dp[i-2]有关,因此可以用两个变量来储存,空间复杂度为O(1)
class Solution {
public int climbStairs(int n) {
if(n<=2){
return n;
}
int pre1 = 2 , pre2 = 1; //初始状态 上两级台阶和一级台阶的方法数
//pre1储存到达当前台阶的方法数,pre2储存到达前一台阶的方法数
for(int i = 2 ; i < n ; i++){
int cur = pre1 + pre2;
pre2 = pre1;
pre1 = cur;
}
return pre1;
}
}
198、 打家劫舍
题目描述:抢劫一排住户,但是不能抢邻近的住户,求最大抢劫量。
定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。
由于不能抢劫邻近住户,如果抢劫了第 i -1 个住户,那么就不能再抢劫第 i 个住户,所以
class Solution {
public int rob(int[] nums) {
int length = nums.length;
if(length==0){return 0;}
if(length==1){return nums[0]; }
if(length==2){return Math.max(nums[1],nums[0]);}
//记录当前index下,前两位的最高金额sum1和前一位sum2
int sum1 = nums[0],sum2 = Math.max(nums[0],nums[1]);
for(int i = 2; i<length; i++){
int current;
current = (sum1+nums[i]>sum2)?sum1+nums[i]:sum2;
sum1 = sum2;
sum2 = current;
}
return sum2;
}
}
简洁版:
public int rob(int[] nums) {
int pre2 = 0, pre1 = 0;
for (int i = 0; i < nums.length; i++) {
int cur = Math.max(pre2 + nums[i], pre1);
pre2 = pre1;
pre1 = cur;
}
return pre1;
}
213.、打家劫舍 II 抢劫环形区域
class Solution {
public int rob(int[] nums) {
int length = nums.length;
if(length==1) return nums[0];
if(length==0) return 0;
//和经典版唯一的区别就是 取第N家就不能取第一家 反之亦然 因此最后再比较这两种情况
//[1:N] [0:N-1]
return Math.max(rob_sub(nums,0,length-1),rob_sub(nums,1,length));
}
public int rob_sub(int[] nums, int front_index, int last_index){
int pre2 = 0, pre1 = 0;
for (int i = front_index; i < last_index; i++) {
int cur = Math.max(pre2 + nums[i], pre1);
pre2 = pre1;
pre1 = cur;
}
return pre1;
}
}