LeetCode121、122、123 买卖股票的最佳时机I II III

121 买卖股票的最佳时机I

题目

在这里插入图片描述

分析

也就是找出两个数字来,让索引大的数字减去索引小的数字,值最大。
动态规划索引为0的数字到索引为i的数字时,最大值dp[i]]为多少,这个过程中需要引入一个min变量来保存从0到i中最小的数字。
公式:

if min >= price[i]
min = price[i] dp[i] = dp[i-1]
else
dp[i] = MAX(dp[i-1], prices[i] - min)

代码

代码中并没有用dp数组来保存,而是直接更新result

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length == 0) return 0;
        int result = 0;
        int min = prices[0];

        for (int i = 1; i < prices.length; i++)
            if (prices[i] < min)
                min = prices[i];
            if (prices[i] > min)
                result = Math.max(result,prices[i]-min);
        return result;
    }
}

122 买卖股票的最佳时机II

题目

在这里插入图片描述

分析

和上一题中要求有些不同,上一题目中,你只可以做一次交易,但是这个题目中你可以做很多次交易。
上一题目是动态规划,这一题目就是贪心算法了,‘尽可能多的完成交易’, 也就是说我尽可能的一点儿也不赔,就是说,我选的序列 i到j , 在这一序列中, i 到 j 的数字应该是递增的,一旦出现下降,立马停止。
那就可以是找到所有的递增子序列,然后算一下加和就可以了。

prices[i] < prices[i-1]
	result += sum
	sum = 0
	min = prices[i]
prices[i] > prices[i-1]
  	sum = max(sum,price[i]-min)

代码

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len == 0) return 0;
        int result = 0;
        int temp = 0;
        int min = prices[0];
        for (int i = 1; i < len; i++) {
            if (prices[i] < prices[i-1]){
                result += temp;
                temp = 0;
                min = prices[i];
            }
            if (prices[i] > min) temp = Math.max(temp, prices[i]-min);
        }
        if (len >= 2 && prices[len-1] >= prices[len-2] ) result += temp;
        return result;
    }
}

买卖股票的最佳时机III

题目

在这里插入图片描述

分析

和前两个又有些不太一样,这回我只可以做两次交易,问最大是多少。
一开始就简单认为在二题贪心的基础上,取出来两个最大的相加就ok啦。
这个想法是错的,可以这么想,在只可以做一次交易的情况下,贪心和动归做出来的结果就是不一样的,有很多数据贪心很明显考虑不全。两次交易同理。

所以这道题还是一道动归题。
两次遍历序列,用predp 和 nextdp 分别来保存,从前向后遍历的时候从0到i的最大值;从后向前遍历的时候从 j 到 len 的最大值。
得到的两个dp数组,让他们两两相加, 取相加和最大的那个。
比如说两个dp已经求出来了, 那么predp[5] + nextdp[5] 就是代表0到5 最大的值 + 5 到len 最大的值。

代码

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if(len == 0) return 0;
        int[] predp = new int[len];
        int[] nextdp = new int[len];
        int premix = prices[0];
        int nextmax = prices[len-1];
        int result = 0;

        for (int i = 1; i < len; i++) {
            if (premix >= prices[i]){
                premix = prices[i];
                predp[i] = predp[i-1];
            }else predp[i] = Math.max(predp[i-1],prices[i]-premix);
        }
        
        for (int i = len-2; i >= 0; i--) {
            if (nextmax < prices[i]){
                nextmax = prices[i];
                nextdp[i] = nextdp[i+1];
            }else nextdp[i] = Math.max(nextdp[i+1], nextmax-prices[i]);
            result = Math.max(predp[i] + nextdp[i],result);
        }
        return result;
    }
}

总结

要分清到底是用动态规划还是贪心来求解,感觉一般出现“尽可能多的……” 就是贪心算法,而出现那种“最大最多最…”的一般就是要用动态规划。

发布了151 篇原创文章 · 获赞 43 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_38595487/article/details/85164362