动态规划算法题汇总整理

1.买卖股票的最好时机(一)

假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益

1.你可以买入一次股票和卖出一次股票,并非每天都可以买入或卖出一次,总共只能买入和卖出一次,且买入必须在卖出的前面的某一天

2.如果不能获取到任何利润,请返回0

3.假设买入卖出均无手续费

数据范围: 0≤n≤105,0≤val≤104

要求:空间复杂度O(1),时间复杂度 O(n)

思路解析:

     1.只能买卖一次,也就是找到其中的最小的,找到最大的元素

      2.假设第一天就是最小的,那就从第二天开始判断,当第二天比min小的时候,min赋值,大的情况,计算利润和第一天比较

    非动态规划解法:

public int maxProfit (int[] prices) {
        // write code here
        //健壮性判断
        if(prices==null||prices.length==0) {
            return 0;
        }
        //假设第一天是最小的
        int min = prices[0];
        int max = 0;
        //从第二天开始进行判断
        for(int i=1;i<prices.length;i++) {
            if(prices[i]<min) {
                min = prices[i];
            }else{
                int temp =  prices[i]-min;
                if(max<temp) {
                    max = temp;
                }
            }
        }
        return max;
    }

动态规划解决:

    找到动态规划公式:

     即当前得利润和前一天进行比较。

     dp[i] = Max(prices[i] - min,dp[i-1]);

  

public int maxProfit (int[] prices) {
        // write code here
        //健壮性判断
        if(prices==null||prices.length==0) {
            return 0;
        }
        int[] dp = new int[prices.length];
        //备忘录
        dp[0] = 0;
        int min = prices[0];
        for(int i=1;i<prices.length;i++) {
            min = Math.min(min,prices[i]);
            dp[i] = Math.max(prices[i]-min,dp[i-1]);
        }
        return dp[prices.length-1];
    }

2.买卖股票的最好时机(二)

假设你有一个数组prices,长度为n,其中prices[i]是某只股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益

1. 你可以多次买卖该只股票,但是再次购买前必须卖出之前的股票

2. 如果不能获取收益,请返回0

3. 假设买入卖出均无手续费

数据范围: 1≤n≤1×105 ,1≤prices[i]≤104

要求:空间复杂度 O(n),时间复杂度O(n)

进阶:空间复杂度O(1),时间复杂度O(n)

思路解析:和题一不同的是可以多次购买股票。

                  这种情况下,只要某一天比前一天有利润就可以卖了

     

public int maxProfit (int[] prices) {
        // write code here
        if(prices==null||prices.length==0) {
            return 0;
        }
        int res = 0;
        for(int i=1;i<prices.length;i++) {
            if(prices[i]>prices[i-1]){
                res+=prices[i]-prices[i-1];
            }
        }
        return res;
    }

动态规划:

      dp[i] = dp[i-1]+price[i]-price[i-1] 

public int maxProfit (int[] prices) {
        // write code here
        if(prices==null||prices.length==0) {
            return 0;
        }
        int[] dp = new int[prices.length];
        dp[0] = 0;
        for(int i=1;i<prices.length;i++) {
            if(prices[i]>prices[i-1]) {
                dp[i] = dp[i-1]+prices[i]-prices[i-1];    
            }else{
                dp[i] = dp[i-1];
            }
        }
        return dp[prices.length-1];
        
    }

3.买卖股票得最好时机(三)

假设你有一个数组prices,长度为n,其中prices[i]是某只股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益
1. 你最多可以对该股票有两笔交易操作,一笔交易代表着一次买入与一次卖出,但是再次购买前必须卖出之前的股票
2. 如果不能获取收益,请返回0
3. 假设买入卖出均无手续费

public int maxProfit (int[] prices) {
        // write code here
        if(prices==null||prices.length==0) {
            return 0;
        }
        //buy1代表第一次买入 sell1代表第一次买入和卖出
        int buy1 = -prices[0],sell1 = 0;
        //buy2 代表买入2次,卖出一次;sell2代表2次买入卖出
        int buy2 = -prices[0],sell2 = 0;
        
        //从第二天开始卖
        for(int i=1;i<prices.length;i++) {
            if(-prices[i]>buy1) {
                buy1 = -prices[i];//第一次买入的最大利润
            }
            if(buy1+prices[i]>sell1) {
                sell1 = buy1+prices[i];//第一次买入卖出的最大利润
            }

            //第二次买入一次卖出情况下
            if(sell1-prices[i]>buy2) {
                buy2 = sell1-prices[i];//第二次买入一次卖出情况最大利润
            }

            //两次情况
            if(buy2+prices[i]>sell2) {
                sell2 = buy2+prices[i];
            }
        }
        return sell2;
    }

x.动态规划总结

     动态规划3要素:

          1.dp数组

         2.dp备忘录

         3.dp[i]计算公式

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值