🚝1.爬楼梯
题目解析:f(x)=f(x-1)+f(x-2)为状态转移方程,但是如果使用递归可能会使得时间复杂度过大,可以定义一个map存储已经计算过的值。
代码
class Solution {
Map<Integer,Integer> map=new HashMap<>();
public int climbStairs(int n) {
if(map.containsKey(n)){return map.get(n);}
if(n==0){map.put(n,1);return 1;}
if(n==1){map.put(n,1);return 1;}
if(n==2){map.put(n,2);return 2;}
else{map.put(n,climbStairs(n-1)+climbStairs(n-2));return map.get(n);}
}
}
🚝2.买卖股票的最佳时机
题目解析 首先,暴力法两次循环可以得到答案
class Solution {
public int maxProfit(int[] prices) {
//保存最终结果
int res=0;
for(int i=0;i<prices.length;i++){
//保存以某一天价格买入能赚到最多的利润
int temres=0;
for(int j=i+1;j<prices.length;j++){
//找到最高价格卖出
temres=Math.max(temres,prices[j]-prices[i]);
}
res=Math.max(temres,res);
}
return res;
}
}
使用动态规划:
class Solution {
public int maxProfit(int[] prices) {
int minPrice=Integer.MAX_VALUE;
int maxProfit=0;
for(int i=0;i<prices.length;i++){
minPrice=Math.min(minPrice,prices[i]);
maxProfit=Math.max(maxProfit,prices[i]-minPrice);
}
return maxProfit;
}
}
🚝3.最大子序和
题目解析 使用动态规划的方法,将每个元素以当前元素结尾的最大子序和保存起来, f(i)代表以第 i 个数结尾的「连续子数组的最大和」
,可以写出动态规划转移方程
f(i)=max{f(i−1)+nums[i],nums[i]}
代码
class Solution {
public int maxSubArray(int[] nums) {
int max=nums[0];
for(int i=1;i<nums.length;i++){
nums[i]=(nums[i-1]+nums[i])>nums[i]?nums[i-1]+nums[i]:nums[i];
if(nums[i]>max){max=nums[i];}
}
return max;
}
}
🚝4.打家劫舍
题目解析
如果只有两间房屋,则由于两间房屋相邻,不能同时偷窃,只能偷窃其中的一间房屋,因此选择其中金额较高的房屋进行偷窃,可以偷窃到最高总金额。
如果房屋数量大于两间,偷窃到的最高总金额呢?对于第 k (k>2) 间房屋,有两个选项:
①偷窃第 k 间房屋,那么就不能偷窃第 k−1 间房屋,偷窃总金额为前 k-2 间房屋的最高总金额与第 k 间房屋的金额之和。
②不偷窃第 k 间房屋,偷窃总金额为前 k−1 间房屋的最高总金额。
代码
class Solution {
public int rob(int[] nums) {
if(nums==null||nums.length==0){return 0;}
if(nums.length==1){return nums[0];}
if(nums.length==2){return Math.max(nums[0],nums[1]);}
int db[]=new int[nums.length];
db[0]=nums[0];
db[1]=Math.max(nums[0],nums[1]);
for(int i=2;i<nums.length;i++){
db[i]=Math.max(db[i-1]+0,db[i-2]+nums[i]);
}
return db[nums.length-1];
}
}
🚝5.打家劫舍 II
题目解析 打家劫舍的升级版,环状排列意味着第一个房子和最后一个房子中不能同时偷窃,因此可以把此环状排列房间问题化为两个单排排列房间子问题:偷第一间与偷最后一间。
代码
class Solution {
public int rob(int[] nums) {
int length=nums.length;
if(nums==null||length==0){return 0;}
if(length==1){return nums[0];}
if(length==2){return Math.max(nums[0],nums[1]);}
return Math.max(robTwo(Arrays.copyOfRange(nums,1,length)),robTwo(Arrays.copyOfRange(nums,0,length-1)));
}
public int robTwo(int[] nums){
int slow=0;
int fast=0;
int temp=0;
for(int num:nums){
temp=fast;
fast=Math.max(num+slow,fast);
slow=temp;
}
return fast;
}
}