leetcode题解:动态规划


🚝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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值