122. Best Time to Buy and Sell Stock II

本文探讨在无限次交易机会下,如何通过算法找出最佳的股票买卖时机以获得最大利润。介绍了通过寻找down点和top点来确定交易对,并提出了一种更直观的算法实现方式,只需遍历一次数组即可计算出最大收益。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Description
在这里插入图片描述
2、题解思路
该题是在121. Best Time to Buy and Sell Stock的基础上进行改进的,在121中每一次至多只能进行一笔交易,但在该问题中交易次数是不限制的,因此也加大了难度,但其思路仍然与121类似,一样可以把所有的数值看做还是二维平面上的点,该时刻的数值就是点的高度。以用例[7,1,5,3,6,4]为例。可以画出如下的图像。
在这里插入图片描述
在图中我们可以定义两类点,一类为down点,一类为top点。down点为比右边的点还低的点,top点为比右边的点还高的点。在下图中down点用绿色进行标记,top点用紫色进行标记。要使得总的收益最大应该满足最近的一堆(top-down)点进行交易,累计获取收益。显然在下图中我们也可以得出看到prices[5]−prices[2]&lt;(prices[5]−prices[4])+(prices[3]−prices[2])prices[5]-prices[2]&lt;(prices[5]-prices[4])+(prices[3]-prices[2])prices[5]prices[2]<(prices[5]prices[4])+(prices[3]prices[2]),即图中两条蓝线的长度之和大于黄线的长度。
在这里插入图片描述
因此最终会的最大收益值为最近的所有top点与down点对的收益值的累加。

3、代码实现(java)
该算法只需要遍历一遍便可以找到所有的down-top点对,因此时间复杂度为O(n),没有开辟额外的空间,空间复杂度为O(1)。

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length==0)return 0;
        int maxProfit = 0;
        int top = prices[0];
        int down = prices[0];
        int i =0;
        while(i<prices.length-1){
            //find the down point
            //attwntion,the equal sign can not ignore,because it will cause the death loop with the case prices=[3,3]
            while(i<prices.length-1&&prices[i]>=prices[i+1]){
                i++;
            }
            down = prices[i];
            //find the top point
            while(i<prices.length-1&&prices[i]<=prices[i+1]){
                i++;
            }
            top = prices[i];
            maxProfit += (top - down);
            // System.out.println("i="+i);
        }
        return maxProfit;   
    }
}

4、反思与改进
考虑下图,我们发现最终的最大收益就是橙色线段的长度,其刚好为以下的各个彩色线段的长度之和,那么和上述的方法进行类比,我们可以发现其实最大收益就是各个线段的累加,在上述的例子中就是两条蓝色线段的累加,而在该例子中便是黄、绿、蓝和紫四条线段的累加。在上述的方法中,该例子在i=2时是一个down点,i=6是一个down点(结束点)他们都遵循这样的规律,即只要prices[i+1]>prices[i],那么就把prices[i+1]-prices[i]的值累加到最大收益的结果当中。
在这里插入图片描述
因此可以得到以下代码,时间复杂度和空间复杂端均不变,但采用等价的方法使得代码更加清晰和直观。

class Solution {
    public int maxProfit(int[] prices) {
        int maxprofit = 0;
        for (int i = 0; i < prices.length-1; i++) {
            if (prices[i+1] > prices[i])
                maxprofit += prices[i+1] - prices[i];
        }
        return maxprofit;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值