力扣_动态规划

爬楼梯

//设爬x层的梯子的方法有f(x)种,那么f(x) = f(x-1)+f(x-2);
//爬1层梯子的方式有一种
//爬2层梯子的方式有两种
//爬3层梯子的方式有三种
//爬4层梯子的方式有五种
class Solution {
    public int climbStairs(int n) {
        //当n为1的时候,没有rev[2],所以要加特殊判断
        if(n == 1){
            return 1;
        }
        int[] rev = new int[n+1];
        rev[0] = 0;
        rev[1] = 1;
        rev[2] = 2;
        for(int i = 3;i < n+1;i++){
            rev[i] = rev[i-1] + rev[i-2];
        }
        return rev[n];
    }
}
 
 

 

买卖股票的最佳时机

// //要取得前后两者的最大值之差
// //可以用暴力法,循环得到每次差值,取得最大值
// //但是这个方法会超时
// class Solution {
//     public int maxProfit(int[] prices) {
//         //求价格的长度
//         int n = prices.length;
//         //设置返回的最大值
//         int max = 0;
//         for(int i = 0;i < n-1;i++){
//             for(int j = i+1;j < n;j++){
//                 if((prices[j]-prices[i]) > max){
//                     max = prices[j] - prices[i];
//                 }
//             }
//         }
//         return max;
//     }
// }

//这题需要思考的是每次差值都是后面减去前面的一个数
//而最大的差值无非就是在一范围内取得最小值与其后的元素差值
//一个区间可能会遇见许多个这样的差值,每次用后面得到的差值与前一项的作比较取的最大值
//往下继续比较即得出全局的最大差值
class Solution {
    public int maxProfit(int[] prices) {
        //某一区间中的最小值
        int minValue = Integer.MAX_VALUE;
        //返回的最大值
        int max = 0;
        //数组长度
        int n = prices.length;
        for(int i = 0;i < n;i++){
            //顺序得到每一区间的最小值
            if(minValue > prices[i]){
                minValue = prices[i];
            }else{
                //顺序得到这一区间的最大值,并取上一次的最大值做比较,大的保存下来
                if(max < (prices[i]-minValue)){
                    max = prices[i] - minValue;
                }
            }
        }
        return max;

    }
}
 
 

最大子序和

//求最大子序列和,需要暂时的保存前面比最大值小的序列和,因为有可能后面加上某一数据后结果就比之前的要大
//还要注意如果前面的序列和已经小于0,那么就没有保存的意义了,后面寻找最大的序列号就不需要之前的数据了
class Solution {
    public int maxSubArray(int[] nums) {
        //返回的最大子序列和
        //不能设置为0,因为数组中只存在负数,那么返回的也可能是负数
        int max = Integer.MIN_VALUE;
        //暂时的sum和
        int sum = 0;
        //数组的长度
        int n = nums.length;
        for(int i = 0;i < n;i++){
            sum = sum+nums[i];
            if(sum > max){
                max = sum;
            }
            if(sum < 0){
                sum = 0;
            }
        }
        return max;
    }
}
 
 

打家劫舍

//因为不能同时打劫相邻的,因此可以判断上一次打劫的金额与上上次打劫的金额与这个可以打劫的金额想加哪个大
//上次打劫的金额不能加上这次的是因为相邻之间的不能同时打劫
class Solution {
    public int rob(int[] nums) {
        //数组的长度
        int n = nums.length;
        //设置返回的数值
        int max = 0;
        int[] dp = new int[n]; 
        //如果没有住户
        if(n == 0){
            return 0;
        }
        //如果只有一个住户
        if(n == 1){
            return nums[0];
        }
        //如果有两个住户
        if(n == 2){
            return Math.max(nums[0],nums[1]);
        }
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0],nums[1]);
        //如果住户大于两个
        for(int i = 2;i < n;i++){
            dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
        }
        return dp[n-1];
    }
}
posted @ 2022-03-08 11:31  Space-guan  阅读(65)  评论(0)    收藏  举报