1. Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock),
design an algorithm to find the maximum profit.
Example 1:
Input: [7, 1, 5, 3, 6, 4]
Output: 5
max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
Example 2:
Input: [7, 6, 4, 3, 1]
Output: 0
In this case, no transaction is done, i.e. max profit = 0.
記錄當(dāng)前最小的買進(jìn)價格,隨后進(jìn)行賣出,并且和當(dāng)前最大的獲利相比較,如果比當(dāng)前最大的還要大,則更新當(dāng)前最大值,否則繼續(xù)執(zhí)行,最后返回最大值。
class Solution {
public int maxProfit(int[] prices) {
if(prices.length <2)
return 0;
int max = 0;
int minprice = prices[0];
for(int i=0; i<prices.length; i++){
if(prices[i]-minprice>max){
max = prices[i]-minprice;
}
if(minprice>prices[i]){
minprice = prices[i];
}
}
return max;
}
}
2. Best Time to Buy and Sell Stock II
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy
one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at
the same time (ie, you must sell the stock before you buy again).
可以無限次買賣股票,但是必須先賣了才能買新的,思路是從第二天開始,如果今日價格比昨天高,那么則可以昨日買入,今日賣出,而到了明日又可以重復(fù)該過程直到利潤最大值。
class Solution {
public int maxProfit(int[] prices) {
if(prices.length < 2){
return 0;
}
int sum = 0;
for(int i=1; i<prices.length; i++){
if(prices[i-1]<prices[i]){
sum += prices[i]-prices[i-1];
}
}
return sum;
}
}
3. Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
第一種方法比較簡單,就是當(dāng)成兩個兩個stcokI 來求解,,即求[0,i],[i+1,n]兩個最大值之和。時間復(fù)雜度優(yōu)化后為O(n)。
class Solution {
public int maxProfit(int[] prices) {
if(prices.length < 2){
return 0;
}
int[] startprices = new int[prices.length];
int[] endprices = new int[prices.length];
for(int i=0; i<prices.length; i++){
startprices[i] = 0;
endprices[i] = 0;
}
int minprices = prices[0];
for(int i=1; i<prices.length; i++){
startprices[i] = Math.max(startprices[i-1], prices[i]-minprices);
minprices = Math.min(minprices, prices[i]);
}
int maxprices = prices[prices.length-1];
for(int i=prices.length-2; i>=0; i--){
endprices[i] = Math.max(endprices[i+1], maxprices-prices[i]);
maxprices = Math.max(maxprices, prices[i]);
}
int max = 0;
for(int i=0; i<prices.length; i++){
max = Math.max(max, startprices[i]+endprices[i]);
}
return max;
}
}
4. Best Time to Buy and Sell Stock IV
Say you have an array for which the *i*th
element is the price of a given stock on day *i*.
Design an algorithm to find the maximum profit. You may complete at most **k** transactions.
**Note:**You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
**Credits:**Special thanks to [@Freezen](https://oj.leetcode.com/discuss/user/Freezen) for adding this problem and creating all test cases.
這題使用動態(tài)規(guī)劃
我們定義local[i][j]為在到達(dá)第i天時最多可進(jìn)行j次交易并且最后一次交易在最后一天賣出的最大利潤,此為局部最優(yōu)。然后我們定義global[i][j]為在到達(dá)第i天時最多可進(jìn)行j次交易的最大利潤,此為全局最優(yōu)。它們的遞推式為:
local[i][j] = max(global[i - 1][j - 1] + max(diff, 0), local[i - 1][j] + diff)
global[i][j] = max(local[i][j], global[i - 1][j])
其中局部最優(yōu)值是比較前一天并少交易一次的全局最優(yōu)加上大于0的差值,和前一天的局部最優(yōu)加上差值中取較大值,而全局最優(yōu)比較局部最優(yōu)和前一天的全局最優(yōu)。
如果k的值遠(yuǎn)大于prices的天數(shù),比如k是好幾百萬,而prices的天數(shù)就為若干天的話,上面的DP解法就非常的沒有效率,應(yīng)該直接用[Best Time to Buy and Sell Stock II 的方法來求解。
class Solution {
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if(n<2){
return 0;
}
if(k>=n){
return maxstock(prices);
}
int[][] g = new int[n][k+1];
int[][] l = new int[n][k+1];
for(int i=1; i<n;i++){
int diff = prices[i]-prices[i-1];
for(int j=1;j<k+1;j++){
l[i][j] = Math.max(g[i-1][j-1]+Math.max(diff, 0), l[i-1][j]+diff);
g[i][j] = Math.max(g[i-1][j], l[i][j]);
}
}
return g[n-1][k];
}
public int maxstock(int[] prices){
if(prices.length < 2){
return 0;
}
int sum = 0;
for(int i=1; i<prices.length; i++){
if(prices[i-1]<prices[i]){
sum += prices[i]-prices[i-1];
}
}
return sum;
}
}