1.題目
題目地址(122. 買賣股票的最佳時機 II - 力扣(LeetCode))
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/
題目描述
給你一個整數陣列 prices
,其中 prices[i]
表示某支股票第 i
天的價格。
在每一天,你可以決定是否購買和/或出售股票。你在任何時候 最多 只能持有 一股 股票。你也可以先購買,然後在 同一天 出售。
返回 你能獲得的 最大 利潤 。
示例 1:
輸入:prices = [7,1,5,3,6,4] 輸出:7 解釋:在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5 - 1 = 4。 隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6 - 3 = 3。 最大總利潤為 4 + 3 = 7 。
示例 2:
輸入:prices = [1,2,3,4,5] 輸出:4 解釋:在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5 - 1 = 4。 最大總利潤為 4 。
示例 3:
輸入:prices = [7,6,4,3,1] 輸出:0 解釋:在這種情況下, 交易無法獲得正利潤,所以不參與交易可以獲得最大利潤,最大利潤為 0。
提示:
1 <= prices.length <= 3 * 104
0 <= prices[i] <= 104
2.題解
2.1 動態規劃
思路
動態規劃最重要的是找到狀態轉移方程:1.哪兩種狀態 2.轉移的值是什麼
在這裡:
1.持有股票/未持有股票
2.當前利潤
三步走:
1.初始化
2.狀態轉移
3.返回結果
程式碼
- 語言支援:C++
C++ Code:
class Solution {
public:
int maxProfit(vector<int>& prices) {
// 初始化沒有股票和持有股票的情況
int dp0 = 0, dp1 = -prices[0];
int n = prices.size();
for(int i = 1; i < n; i++){
// 當前未持有股票:上一次就未持有股票 / 上一次持有股票本次賣掉
dp0 = max(dp0, dp1 + prices[i]);
// 當前持有股票: 上一次就持有股票 / 上一次未持有股票本次買入
dp1 = max(dp1, dp0 - prices[i]);
}
return dp0;
}
};
複雜度分析(最佳化後)
- 時間複雜度:\(O(n)\),同上。
- 空間複雜度:\(O(1)\),因為只用了常數個額外變數。
2.2 貪心演算法
思路
這裡貪心的主要策略是實現區域性最優的方式,我們很容易發現,假設我們選擇從1買入,5賣出的方式區域性最優;
那麼我們1買入,2賣出;2買入,3賣出....4買入,5賣出這樣的選擇也是最優的
也就是說,我們可以將區間長度選擇簡短為1,每次都選擇淨利潤大於0的買入賣出即可!
程式碼
class Solution {
public:
int maxProfit(vector<int>& prices) {
int ans = 0, n = prices.size();
for(int i = 1; i < n; i++){
ans += max(0, prices[i] - prices[i-1]);
}
return ans;
}
};
複雜度分析
- 時間複雜度:\(O(n)\),其中\(n\)是價格陣列的長度。我們只需遍歷一次價格陣列。
- 空間複雜度:\(O(1)\),因為只使用了常數個額外變數。