LeetCode简易题解--121、122、123、188
2017-09-18 22:44
267 查看
121. Best Time to Buy and Sell Stock
目标是找到max(prices[j]−prices[i]), for every i and j such that j > i.
直接用两层循环可能会超时。
更好的方法是遍历一遍
prices[]数组,每一次遍历执行一下两个操作:
记录下目前为止遇到的最小值
计算当前
price与最小值的差值,与已经得到的前面部分的最大值作比较,取较大者。
代码如下:
class Solution { public: int maxProfit(vector<int>& prices) { int n = prices.size(); if (n == 1 || n == 0) return 0; vector<int> res(n, 0); int min = prices[0]; int final_res = 0; for (int i = 1; i < n; ++i) { if (prices[i] < min) min = prices[i]; if (prices[i] - min > final_res) { final_res = prices[i] - min; } } return final_res; } };
122. Best Time to Buy and Sell Stock II
与上一道题同样,是一道简单题,但是直接用两层循环可能会超时。可以对
prices[]进行遍历,找到每一段升序子段,结果加上首尾差值即可。
代码如下:
class Solution { public: int maxProfit(vector<int>& prices) { int n = prices.size(); if (n == 1 || n == 0) return 0; int cur_max, cur_min; cur_max = cur_min = prices[0]; int final_res = 0; for (int i = 1; i < n; ++i) { if (prices[i] > prices[i - 1]) { cur_max = prices[i]; } else { final_res += cur_max - cur_min; cur_min = cur_max = prices[i]; } } final_res += prices[n - 1] - cur_min; return final_res; } };
更简洁的方法是:对每一个
prices[i],如果
prices[i] - prices[i-1] > 0,则结果加上该差值。只要后一个数比前一个数大,就加上两数的差值,效果与以上方法是一样的。
123. Best Time to Buy and Sell Stock III
初始收益profit = 0,购买时
profit -= prices[i],出售时
profit += prices[i]。
这里有四个变量:
buy1:表示只买了一块石头的收益
sell1:表示买一块并卖了一块石头的收益
buy2:表示买了第二块石头时的收益,根据题目,此时肯定已经买卖过一次石头了
sell2:表示卖了第二块石头时的收益
对
prices[]进行遍历,每一次遍历都计算出以上4个值,则最后的结果必定是
max(sell1, sell2)。
class Solution { public: int maxProfit(vector<int>& prices) { if (prices.size() <= 1) return 0; int buy1 = INT_MIN, buy2 = INT_MIN; int sell1 = 0, sell2 = 0; for (int i = 0; i < prices.size(); ++i) { sell2 = max(sell2, buy2 + prices[i]); buy2 = max(buy2, sell1 - prices[i]); sell1 = max(sell1, buy1 + prices[i]); buy1 = max(buy1, -prices[i]); } return sell2 < 0 ? 0 : sell2; } };
以上代码的一些解释:
Q: 为何计算顺序是
sell2、
buy2、
sell1、
buy1?
A: 因为每一个值都是根据上一步计算的结果推出来的。以
sell2为例,它是根据上一步的
buy2推导出来的,若是
buy2先于
sell2计算,则在计算
sell2时,所使用的
buy2的值是这一步的结果,而不是上一步的结果。其他变量类似。
Q: 为什么直接返回
sell2?
A:
sell2是根据
buy2计算的,
buy2是根据
sell1计算的,这会导致
sell2始终比
sell1大。
PS:以上思路来自LeetCode的Disscussion。
188. Best Time to Buy and Sell Stock IV
用动态规划的思路来写。将买卖一次石头称作一次事务,只有执行至少一次事务时才会有收益。
dp[i][j]表示:
prices[]从 0 到 j-1 个元素并且执行了 i 个事务时的最大收益。
首先确定边界:
dp[i][0] = 0 : 第一个元素的地方收益当然为0
dp[0][j] = 0 : 一次事务都没执行,收益当然为0
现在考虑一般情况:
dp[i][j]表示到
prices[j-1]并且执行了
j次事务时的最大收益,该值来源于两个方面:
dp[i][j-1]:到
prices[j-1](即第j天)时,事务数量没有增加(没有卖出石头,收益也就不会增加)
max( prices[j] - prices[jj] + dp[i-1, jj] {0<=jj<j} ): 到
prices[j-1](即第j天)时,事务数量增加1
以上第二个值的解释:
prices[jj]之前(0到jj-1)视为一个执行了i-1次事务的子段,
dp[i-1][jj]为此时的最大收益,该值加上jj+1到j之间的最大差值,就可能是
dp[i][j]。但是这个jj可能会有多个值,因此这些
prices[j] - prices[jj] + dp[i-1, jj] {0<=jj<j}中的最大值即是
dp[i][j]的两个可能来源之一。
而
dp[i][j]就是以上两个值之中的最大值:
p[i][j] = max(dp[i][j-1], max( prices[j] - prices[jj] + dp[i-1, jj])) = max(dp[i, j-1], prices[j] + max(dp[i-1, jj] - prices[jj]));
另外,记n为数组长度,则最多有n/2个事务(每个事务至少涉及两个元素),
因此当k>n/2时,该题跟122题是一样的。
代码如下:
class Solution { public: int maxProfit(int k, vector<int>& prices) { if (prices.size() <= 1) return 0; int n = prices.size(); if (k > n / 2) return quick_solve(prices); vector<vector<int> > dp(k + 1, vector<int>(n, 0)); for (int i = 1; i <= k; ++i) { int tmp_max = -prices[0]; for (int j = 1; j < n; ++j) { dp[i][j] = max(dp[i][j - 1], tmp_max + prices[j]); tmp_max = max(tmp_max, dp[i - 1][j] - prices[j]); } } return dp[k][n - 1]; } int quick_solve(vector<int>& prices) { int n = prices.size(); int res = 0; for (int i = 1; i < n; ++i) { if (prices[i] > prices[i - 1]) res += prices[i] - prices[i - 1]; } return res; } };
相关文章推荐
- LeetCode 121、122、123、188:Best Time to Buy and Sell Stock
- leetcode(121)(122)(123)(188) Best Time to Buy and Sell Stock I/II/III/IV JAVA代码
- leetcode_[python/C++]_121/122/123/188.Best Time to Buy and Sell Stock I/II/III/IV
- 121 122 123 188 Best Time to Buy and Sell Stock
- leetcode【121+122+123 best time to buy and sell stock】【python】
- leetcode 121 122 123 . Best Time to Buy and Sell Stock
- LeetCode121/122/123/188 Best Time to Buy and Sell Stock<股票> I/II/III/IIII----DP+Greedy**
- leetcode121、122、123
- LeetCode 121, 122, 123. Best Time to Buy and Sell Stock i, ii, iii
- LeetCode简易题解--039
- [LeetCode]题解(python):122-Best Time to Buy and Sell Stock II
- LeetCode简易题解--084,085
- LeetCode题解:123. Best Time to Buy and Sell Stock III
- 【计蒜客系列】挑战难题:119,120,121,122,123,125,126,127
- 121~123 188 Best Time to Buy and Sell StockI II III IV
- LeetCode简易题解--120
- LeetCode 121-123 Best Time to Buy and Sell Stock I II III
- LeetCode简易题解--053
- LeetCode简易题解--098、099
- LeetCode简易题解--103