买卖股票大合集

刷题刷题往死里刷。


121. 买卖股票的最佳时机

链接

121. 买卖股票的最佳时机

思路:

二次做所以有思路了, 从头遍历数组,维持一个最小值,且遇到一个值就计算差值,且维护这个最大值为答案。

class Solution {
    public int maxProfit(int[] prices) {
        int min = prices[0], ans = 0;
        for(int i = 0; i < prices.length; i++){
            ans = Math.max(ans, prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        return ans;
    }
}

122. 买卖股票的最佳时机 II

链接

. - 力扣(LeetCode)

思路:

由于可以在同一天买入卖出,可以将收入理解为所有利润和,有差的全部记录下来,没有的默认当天买入卖出。

class Solution {
    public int maxProfit(int[] prices) {
        //这个是求利润和
        int len = prices.length;
        int ans = 0;
        for(int i = 1; i < len; i++){
            if(prices[i] > prices[i - 1]){
                ans+=(prices[i] - prices[i -1]);
            }
        }
        return ans;
        
    }
}

 123.买卖股票的最佳时机III

. - 力扣(LeetCode)

自己的思路

 可以将题目理解为找两段不相交的相差最大的数。

不会写

官方题解

感觉很合理但是又想不出来。

class Solution {
    public int maxProfit(int[] prices) {
        int n = prices.length;
        int buy1 = -prices[0], sell1 = 0;//买入一个,已经完成一单(当天买入卖出)
        int buy2 = -prices[0], sell2 = 0;//买了两个,已经完成两单(同一天买入卖出并再次卖如, 买入卖出两次)
        for(int i = 1; i < n; i ++){
            buy1 = Math.max(buy1, -prices[i]);//买入价格更低的
            sell1 = Math.max(sell1, buy1 + prices[i]);//找差更高的价格
            buy2 = Math.max(buy2, sell1 - prices[i]);//是否买入
            sell2 = Math.max(sell2, buy2 + prices[i]);//是否卖出
        }
        return sell2;

    }
}

收获

初始化
int buy1 = -prices[0], sell1 = 0;//买入一个,已经完成一单(当天买入卖出)
int buy2 = -prices[0], sell2 = 0;//买了两个,已经完成两单(同一天买入卖出并再次卖如, 买入卖出两次)
状态转移式子
buy1 = Math.max(buy1, -prices[i]);//买入价格更低的
sell1 = Math.max(sell1, buy1 + prices[i]);//找差更高的价格
buy2 = Math.max(buy2, sell1 - prices[i]);//是否买入
sell2 = Math.max(sell2, buy2 + prices[i]);//是否卖出

有点难,多理解


188.买卖股票的最佳时机

. - 力扣(LeetCode)

自己的思路

感觉跟上面那道题很像,改成k次循环而不是二次就好了。

跟官方题解的方法不一样,懒得看了。

class Solution {
    public int maxProfit(int k, int[] prices) {
        int[][] arr = new int[k+1][2];//k次买入卖出
        for(int i = 0 ; i <= k; i++){
            arr[i][0] = -prices[0];//buy初始化
            arr[i][1] = 0;//当天买入卖出
        }
        int len = prices.length;
        for(int i = 0; i < len; i++){
            for(int j = 1; j <= k ; j++){
                arr[j][0] = Math.max(arr[j][0], arr[j-1][1] - prices[i]);//等于上一次arr[j][1]剩下的前减价格
                arr[j][1] = Math.max(arr[j][1], arr[j][0] + prices[i]);
            }
        }
        return arr[k][1];
    }
}

309.买卖股票的最佳时机含冷冻期

. - 力扣(LeetCode)

自己的思路

感觉不太会做,只是把上面那道题的k定成了len,并且修改了dp[i][0]的转移公式,如果我要买,我得买两天之前的。

但是答案是错误的,看看是不是初始化有问题。

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        int[][] dp = new int[len+1][2];
        for(int i = 0; i <= len; i++){
            dp[i][0] = -prices[0];
            dp[i][1] = 0;
        }
        //那就当作买卖k次
        for(int i = 2; i <= len; i++){
            dp[i][0] = Math.max(dp[i][0] , dp[i-2][1] - prices[i-1]);//买或者不买
            dp[i][1] = Math.max(dp[i][1], dp[i][0] + prices[i-1]);//表示利润的和,用加来表示
        }
        return dp[len][1];
        
    }
}

官方题解

妙啊,既然买入卖出是两个状态,那完全可以把冷冻期也作为一个状态。

理解三个状态

f[i][0]: 手上持有股票的最大收益
f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益

官方代码题解

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        int[][] dp = new int[len][3];
        dp[0][0] = -prices[0];
        for(int i = 1; i < len; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][2] - prices[i]);//持有股票的最大利润
            dp[i][1] = dp[i-1][0] + prices[i];//今天卖出票,冷冻期,不考虑当天买入卖出,持有股票的最大利润
            dp[i][2] = Math.max(dp[i-1][1], dp[i-1][2]);//前一天是冷冻期或者不是冷冻期,反正前一天不可能持有股票,那是冷冻期的事
        }
        return Math.max(dp[len-1][2], dp[len-1][1]);//最后要注意比较,因为当天卖出的可能还没有传给最后的
    }
}

收获

dp数组的设置
f[i][0]: 手上持有股票的最大收益
f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益
int[][] f = new int[n][3];
f[0][0] = -prices[0];

遍历方式

为什么这道题跟上一题的遍历方式不一样,没有将次数记录在状态里,只是在遍历n个股票,尝试找出最大的收益。

上一题要求的是恰好k次交易,所以需要记录交易次数。

递归方程
dp[i][0]

dp[i][0]表示在前i个股票中,手中持有股票的最大利润。

它的转移方程为持有前一天的股票,或者当天自己买入(原始钱是前一天的最大利润,很好理解,要持有股票的最大利润,就是拿前一天的最大利润买今天的)。即

dp[i][0] = Math.max(dp[i-1][0], dp[i-1][2] - prices[i]);

 

 dp[i][1]

dp[i][1]表示在前i个股票中,手中不持有股票的处于冷冻期的最大收益。

这个的转移比较难理解,多看。

手中不持有股票的冷冻期,意味着我前一天要卖出,不过前一天卖出的利益并不是最大利润,所以直接用前一天持有股票的最大利润减去前一天的股票价格,而不是继承。

  • 为什么冷冻期是前一天的持有股票时的利润加今天卖出的股票价钱,不是加昨天的最大价钱,如果我当天是冷冻期的话,不是应该是昨天卖出的吗。

 这里我们需要将冷冻期理解为卖出当天开始,为什么呢

  • 之前的题目是可以多次在当天买入卖出的,但是在这道题,当天卖出了之后不能再买入了,所以可以理解为,这道题在当天卖出的时候就是冷冻期了,包括后面的第一天也是冷冻期。

所以dp[i][1] = dp[i-1][0] + price[i].

而由于当天不卖出的冷冻期,不需要对股票做任何操作

 

dp[i][2]

dp[i][2]表示在前i个股票,手中不持有股票的不处于冷冻期的最大收益。

不持有股票又不是冷冻期,意味着前一天是冷冻期或者前一天是冷冻期之后的日子,而当天是无法堆股票做任何操作的,所以只需要继承前两天的冷冻期或者非冷冻期的最大利润就可以了。


714.买卖股票的最佳时机含手续费

. - 力扣(LeetCode)

自己的思路

和无手续费的时候其实是一样的,只需要在收入减去费用就可以了,卖出和买入的时候的减费用都行。

跟官方题解没区别,过。

class Solution {
    public int maxProfit(int[] prices, int fee) {
        //一个普通的dp数组而已,只不过在卖出的时候减个交易费就好
        int len = prices.length;
        int[][] dp = new int[len][2];
        dp[0][0] = -prices[0];
        for(int i = 1 ; i < len; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] - prices[i]);//手中无股票的最大利润
            dp[i][1] = Math.max(dp[i-1][1], dp[i][0] + prices[i] - fee);
        }
        return dp[len-1][1];
    }
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值