给定一个数组,它的第 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)