C++算法成长之路:买卖股票的最好时机 II

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

示例 2:

输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例3:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

  • 1 <= prices.length <= 3 * 10 ^ 4
  • 0 <= prices[i] <= 10 ^ 4

我的代码(暴力解法):

class Solution {
public:
    int maxProfit(vector<int>& prices) {
    //定义一些数字和变量
        int pricelength = prices.size();    //保存原数组长度
        int min[pricelength];				//生成保存极小值的数组
        int flag = 0;						//控制买卖顺序,0为买
        int minnum = 0;						//定义极小值数组的第一个元素
        int sum = 0;						//利益总和
        int price[pricelength+2];			//用一个n+2的数组保存
        									//原长为n的数组
		
		//将第一个元素赋值为0,最后一个为最大数值10000,其余的复制
        for(int k = 0; k < pricelength; k++){
            price[k+1] = prices[k];
        }
        price[pricelength+1] = 0 ;  
        price[0] = 10000;

		//根据条件进行第一层判断
        if(pricelength >= 1 && pricelength <= 3*10000){
        	//进行数组遍历
            for(int i = 1;i <=pricelength;i ++){
            	//进行第二层判断
                if(price[i] >=0 && price[i] <= 10000){
                	//如果当前动作为买,则寻找当前极小值保存到数组中
                    if(flag == 0){
                        if(price[i] < price[i+1] && price[i] <= price[i-1]){
                            min[minnum++] = price[i];
                            flag = 1;			//变更操作到卖	
                        }
                    }
					//如果当前动作为卖,则计算求和
                    if(flag == 1){
                        if(price[i] >= price[i+1] && price[i] > price[i-1]){
                            sum += price[i] - min[minnum-1]; 
                            flag = 0;			//变更操作为买
                        }
                    }
                }
       
         
            }
        }
        return sum;
    }

};

思路:
将原长为n的数组复制到为n+2的数组中,第一个定义为0,最后一个为最大长度,保证判断不会越界且能准确找出极大极小值。
将极小值保存在数组中,在找出极大值时直接进行sum求和。

遇到的问题:
在这里插入图片描述
解决方法:在进行判断的时候判断越界,没有考虑到后续i + 1的长度。只需要将判断长度减一就解决啦。

大佬的解法:
作者:数据结构和算法

public int maxProfit(int[] prices) {
    if (prices == null || prices.length < 2)
        return 0;
    int length = prices.length;
    //初始条件
    int hold = -prices[0];//持有股票
    int noHold = 0;//没持有股票
    for (int i = 1; i < length; i++) {
        //递推公式转化的
        noHold = Math.max(noHold, hold + prices[i]);
        hold = Math.max(hold, noHold - prices[i]);
    }
    //最后一天肯定是手里没有股票的时候利润才会最大,
    //所以这里返回的是noHold
    return noHold;
}

贪心算法解决:

public int maxProfit(int[] prices) {
    if (prices == null || prices.length < 2)
        return 0;
    int total = 0, index = 0, length = prices.length;
    while (index < length) {
        //如果股票下跌就一直找,直到找到股票开始上涨为止
        while (index < length - 1 && prices[index] >= prices[index + 1])
            index++;
        //股票上涨开始的值,也就是这段时间上涨的最小值
        int min = prices[index];
        //一直找到股票上涨的最大值为止
        while (index < length - 1 && prices[index] <= prices[index + 1])
            index++;
        //计算这段上涨时间的差值,然后累加
        total += prices[index++] - min;
    }
    return total;
}

最后运行得分:
在这里插入图片描述
不管黑猫白猫,抓到老鼠就是好猫(/doge)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值