文章目錄
-
- 1. 題目來源
- 2. 題目說明
- 3. 題目解析
-
- 方法一:數學+思維+動态規劃+頂級解法
- 方法二:動态規劃+巧妙解法
- 方法三:暴力+正常解法
1. 題目來源
連結:買賣股票的最佳時機
2. 題目說明
給定一個數組,它的第
i
個元素是一支給定股票第
i
天的價格。
如果你最多隻允許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能擷取的最大利潤。
注意你不能在買入股票前賣出股票。
示例 1:
輸入: [7,1,5,3,6,4]
輸出: 5
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。
注意利潤不能是 7-1 = 6, 因為賣出價格需要大于買入價格。
示例 2:
輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種情況下, 沒有交易完成, 是以最大利潤為 0。
3. 題目解析
方法一:數學+思維+動态規劃+頂級解法
來自題解區大佬:121. 買賣股票的最佳時機 - dp 7 行簡約風格

原數組兩個元素的最大差等于求差數組的最大子序和!!!
原數組兩個元素的最大差等于求差數組的最大子序和!!!
原數組兩個元素的最大差等于求差數組的最大子序和!!!
以前好像在哪聽過,又忘記了…忘了就記,就練習,就了解,就吃透。
這個結論簡單推導下就可以得出,比如:一個數組中有 [ a , b , c , d ] [a,b,c,d] [a,b,c,d] 這幾個數,那麼 d d d 與 a a a 的內插補點可以用相鄰兩數的內插補點的最大子序和得出。
f = ( b − a ) + ( c − b ) + ( d − c ) = d − a f=(b−a)+(c−b)+(d−c)=d−a f=(b−a)+(c−b)+(d−c)=d−a
針對最大子數組的動态規劃求解。
參見代碼如下:
// 執行用時 :20 ms, 在所有 C++ 送出中擊敗了20.77%的使用者
// 記憶體消耗 :15.6 MB, 在所有 C++ 送出中擊敗了5.09%的使用者
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.size() <= 1) return 0;
vector<int> vt(prices.size() - 1);
for (int i = 0; i < prices.size() - 1; ++i)
vt[i] = prices[i + 1] - prices[i];
vector<int> dp(vt.size());
dp[0] = max(0, vt[0]);
int max= dp[0];
for (int i = 1; i < vt.size(); ++i) {
dp[i] = max(0, dp[i - 1] + vt[i]);
max= max(max, dp[i]);
}
return max;
}
};
方法二:動态規劃+巧妙解法
針對原問題的動态規劃求解。
d p [ i ] dp[i] dp[i] 表示前 i i i 天的最大利潤,因為我們始終要使利潤最大化,則:
d p [ i ] = m a x ( d p [ i − 1 ] , p r i c e s [ i ] − m i n p r i c e ) dp[i] = max(dp[i-1], \ \ prices[i]-minprice) dp[i]=max(dp[i−1], prices[i]−minprice)
參見代碼如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0) return 0; // 邊界條件
int minprice = prices[0];
vector<int> dp (n, 0);
for (int i = 1; i < n; i++){
minprice = min(minprice, prices[i]);
dp[i] = max(dp[i - 1], prices[i] - minprice);
}
return dp[n - 1];
}
};
方法三:暴力+正常解法
兩次循環,暴力解法。時不時會
TLE
。
// 執行用時 :1820 ms, 在所有 C++ 送出中擊敗了20.77%的使用者
// 記憶體消耗 :14.1 MB, 在所有 C++ 送出中擊敗了5.09%的使用者
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = (int)prices.size(), ans = 0;
for (int i = 0; i < n; ++i){
for (int j = i + 1; j < n; ++j){
ans = max(ans, prices[j] - prices[i]);
}
}
return ans;
}
};