LeetCode初级算法——动态规划类——算法总结

LeetCode初级算法——动态规划类——算法总结

PS:算法并非原创,总结的本意在于温故知新、巩固知识。侵删。

1、爬楼梯
使用JAVA解答,代码如下:

class Solution {
    public int climbStairs(int n) {
        if(n==1)return 1;
        int sum[]=new int[n+1];
        sum[0]=0;sum[1]=1;sum[2]=2;
     for(int i=3;i<=n;i++){
         sum[i]=sum[i-2]+sum[i-1];
     }
        return sum[n];
    }
}

算法解析:
对于n层台阶,一开始可以选择爬1步或者爬2步。选择爬1步的话,对应的后续阶梯为n-1步,爬楼方法为sum[n-1]。对于爬2步,对应的后续阶梯为n-2步,爬楼方法为sum[n-2]。所以sum[n] = sum[n-1]+sum[n-2]。通过已知的1级、2级台阶的爬楼方法数,可以知道后续的数组元素值。

点击查看参考网址

算法占用时空间资源:
在这里插入图片描述

2、买卖股票的最佳时机
使用JAVA解答,代码如下:

 class Solution {
    public int maxProfit(int[] prices) {
        //解法二:动态规划法:用dp[i]表示第i天卖出的收益,则dp[i]=max(price[i]-min,maxProfit)
        //时间复杂度:O(n),空间复杂度:O(1)
        if(prices==null || prices.length==0)
            return 0;
        int len=prices.length;
        int maxprofit=0,min=Integer.MAX_VALUE;
        for(int i=0;i<len;i++){
            if(prices[i]<min)   //维护一个最小值
                min=prices[i];
            else if(prices[i]-min>maxprofit)
                maxprofit=prices[i]-min;
        }
        return maxprofit;
    }
}

算法解析:
这个问题,乍看和数组类中“买卖股票的最佳时机II”很相似,但是本题中规定只能买卖一次,所以需要进行最大收益的比较。
我们用dp[i]表示从第1天到第i天进行一笔交易能获得的最大收益,用min表示买入的最低价格,则dp[i]=max(price[i]-min,maxProfit),其中maxProfit是指已经找到的最大收益。由于只允许一次交易,所以要想获得最大收益,必须在价格最低的时候买入,最高的时候卖出,但是由于必须先买后卖,
也就是使用min表示最低买入,maxprofit表示最大收益。min最终会指向峰谷,而maxprofit一定是先谷后峰的最大差异值。

点击查看参考网址

算法占用时空间资源:
在这里插入图片描述
3、最大子序和
使用JAVA解答,代码如下:

class Solution {
    public int maxSubArray(int[] nums) {// 动态规划法
        int sum=nums[0];
        int n=nums[0];
        for(int i=1;i<nums.length;i++) {
            if(n>0)
            	n+=nums[i];
            else 
            	n=nums[i];
            if(sum<n)
            	sum=n;
        }
        return sum;
    }
}

算法解析:
sum表示整体的最大子数组之和。n存储当前的可能最大值,保留着之前遍历过的最大值的结果。当遍历结果仍然为正数时,n不断计算累计和,通过比较sun和n的大小观察最终的最大子数组之和;当遍历结果已经为负数时,由于在之前的遍历中,sum已经存入最大子数组之和,所以n可以重新赋值,开始新一轮的累加。
(原博文)每次运算只需要前一次的结果,因此并不需要像普通的动态规划那样保留之前所有的计算结果,只需要保留上一次的即可,因此算法的时间和空间复杂度都很小

点击查看参考网址(多种解法)

算法占用时空间资源:
在这里插入图片描述

4、打家劫舍
使用JAVA解答,代码如下:

class Solution {
    public int rob(int[] nums) {
       if (nums.length == 0){
            return 0;
        }
 
        if (nums.length == 1){
            return nums[0];
        }
 
        if (nums.length == 2){
            return Math.max(nums[0], nums[1]);
        }
 
        int[] result = new int[nums.length];   
        result[0] = nums[0];//只有一家的情况下,只能抢这一家了
        result[1] = Math.max(nums[0], nums[1]);//有两家可选的情况下,抢价值最大的那一家
 
        for(int index=2; index < result.length; index++){
            result[index] = Math.max(nums[index] + result[index-2], result[index -1]);
        }
 
        return result[nums.length -1];

    }
}

算法解析:
此题所采用的解法,和第一题“爬楼梯”有点类似,对于多个选择节点的问题,进行分解。对于数组长度为0、为1、为2的情况,按照题目要求进行讨论。对于长度超过2的数组,每一个结果数组的元素值,都建立在已得结果的基础上。对于n个住户,我们可以选择抢夺第一家,然后考虑第三家到最后一家,也可以直接从第二家开始抢夺。由于之前的n-2和n-1家的最佳结果已经存储到result数组中,因此这两种策略的收益分别对应:nums[index]+result[index-2]和result[index-1],我们可以选择其中的最大值,作为最终result[n]的结果。
最后,result[i]中存储的是:i户人家进行抢夺的最佳收益。

点击查看参考网址(多种解法)

算法占用时空间资源:
在这里插入图片描述
补:
动态规划在这四题中,有两种不同的形式,一种是设置参考最值,遍历运算和参考最值比较(2和3),还有一种,是通过结果数组存储每一种结果(1和4),适合多选择结点的题目,选择方式往往可以用迭代思想进行拆解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值