题目:买卖股票的最佳时机III
链接:买卖股票的最佳时机III
首先,我按照自己的思路去尝试着解答,大概的是这样子的:分为两种情况,一次买卖和两次买卖。
一次买卖:实质上就是求一个数组内后面的数与前面数的最大差值
两次买卖:从每次买卖的时长入手,定义了第一次买卖和第二次买卖的时长分别为i和j(加入第一天买入而第二天卖出时长就为2)。接着遍历第一次买卖与第二次买卖各种可能的时长,不断更新最大收益。
代码详解如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dif1 = 0, dif2 = 0, dif; //dif1为一次买卖的最大收益,dif2为两次买卖的最大收益,dif为总的最大收益
int n = prices.size();
int mon, thu; //在两次买卖情况下第一次和第二次买卖的收益
//一次买卖
for(int i = 0; i < n; i++)
{
for(int j = i + 1; j < n; j++)
{
dif1 = max(dif1, prices[j] - prices[i]); //更新最大收益
}
}
//二次买卖
for(int i = 2; i <= n - 2; i++) //i为第一次买卖的时长
{
for(int j = 2; j <= n - 2; j++) //j为第二次买卖的时长
{
for(int k = 0; k <= n - i; k++) //k为第一次买卖的开始
{
for(int s = k + i; s <= n - j; s++) //s为第二次买卖的开始
{
mon = prices[k + i - 1] - prices[k];
thu = prices[s + j - 1] - prices[s];
dif2 = max(dif2, mon + thu); //更新最大收益
}
}
}
}
dif = max(dif1, dif2);
return dif;
}
};
没错,我居然用了四层循环,这应该是比较直观的一种解答,但是从时间复杂度的角度来说是很糟糕的,于是LeetCode给出了下面公正的评判:
看来,还要老老实实再想(看)一些更巧妙地方法。
好吧,2h之后我回来了,带着对强者的敬仰~~
强者一:自动机
原文链接:自动机
强者二:动态规划
通过后复制的LeetCode评测击败100%的代码(找不到原文链接)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
int k=2;
int dp[k+1][2]={0};
//初始化
for(int j=1;j<=k;j++) {
dp[j][0]=0;
dp[j][1]=-prices[0];
}
for(int i=1;i<n;i++){
for(int j=1;j<=k;j++){
dp[j][0] = max(dp[j][0], dp[j][1]+prices[i]);
dp[j][1] = max(dp[j][1], dp[j-1][0]-prices[i]);
}
}
return dp[k][0];
}
};
看完大佬们的思路与代码后发现自己的思路貌似不太“正统”,自己之前是考虑每次买卖的收益,而大多数人是来考虑单次买卖之后的收支,也就是上面自动机与动态规划的基本出发点。看来自己还有很长的路要走~~~~
题外话:
在人生或者职业的各种事务中,性格的作用比智力大得多,头脑的作用不如心情,天资不如由判断力所节制着的自制,耐心和规律。
———海明威《真实的高贵》