Problem
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
Given an example [3,2,3,1,2], return 1
Note
只有一次交易,那么将prices[]数组循环一次,每次循环更新prices[]
历史最小值,并与当日价格相减得到当日利润,同步更新profit最大值。
Solution
public class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) return 0;
int profit = 0;
int min = prices[0];
for (int i = 1; i < prices.length; i++) {
min = Math.min(min, prices[i]);
profit = Math.max(prices[i] - min, profit);
}
return profit;
}
}
Problem
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 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).
Example
Given an example [2,1,2,0,1], return 2
Note
可以有无限次交易,那么在所有股票上涨的区间都进行交易。
Solution
class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) return 0;
int profit = 0;
for (int i = 1; i < prices.length; i++) {
profit += prices[i] > prices[i-1] ? prices[i] - prices[i-1] : 0;
}
return profit;
}
}
Problem
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.
Example
Given an example [4,4,6,1,1,4,2,5], return 6.
Note
买卖股票III有几个值得注意的地方,首先left[0]
, right[len-1]
在循环之前会自动赋0。其二,是分配left[]
和right[]
的空间都要比prices.length
大1。
这道题使用双向动态规划的做法,从prices[0]
向右找prices[i]
以左的最大收益left[i]
,从prices[len-1]
向左找prices[i]
以右的最大收益right[i]
。
最后遍历所有left[i] + right[i]
,得到收益最大值。
Solution
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if (prices == null || len == 0) return 0;
int[] left = new int[len+1];
int[] right = new int[len+1];
int min = prices[0];
int max = prices[len-1];
int profit = 0;
for (int i = 1; i < len; i++) {
min = Math.min(prices[i], min);
left[i] = Math.max(prices[i] - min, left[i-1]);
}
for (int i = len - 2; i >= 0; i--) {
max = Math.max(prices[i], max);
right[i] = Math.max(right[i+1], max - prices[i]);
}
for (int i = 0; i < len; i++) {
profit = Math.max(profit, left[i] + right[i]);
}
return profit;
}
}
Problem
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 k transactions.
Example
Given prices = [4,4,6,1,1,4,2,5], and k = 2, return 6.
Note
首先分析k与len的关系,如果k > len / 2
,相当于比每两天交易一次(昨天买今天卖,明天买后天卖)还要多,那么就存在在同一天买入并卖出的情况。那么就相当于股票交易II中的做法,在所有上涨的情况下都做了交易,返回sum
。
然后分析非上述情况的k
值:建立两个数组,数组local[i][j]
表示在第i
天正好做完第j
次交易的收益,数组global[i][j]
表示在第i
天已经做完第j
次交易的收益。
global[i][j]
是二次优化收益,之前做过的交易总数可能等于j,也可能大于j。
local[i][j]
是当次优化收益,分为两种情况:i-1
天做j-1
次交易的二次优化收益global[i-1][j-1]
,加上一次优化交易的利润:取第i-1天买入、第i天卖出的利润和0的较大者(0表示今日买入并卖出的情况),以达成第j
次交易;i-1
天做j
次交易的当次优化收益local[i-1][j]
,加上一次等效交易的利润:即第i-1
天完成j
次交易等效于第i
天完成j
次交易的情况:假设第i
天股票价格继续上涨,就相当于第i-1
天卖出后继续买入,第i
天又卖出,相当于第i-1
天没有交易操作,第i
天卖出才完成了第j
次交易。local[i][j]
最后取上述两种情况的较大值。
Solution
1.
class Solution {
public int maxProfit(int k, int[] prices) {
int len = prices.length;
if (prices == null || len == 0) return 0;
if (k + k > len) {
int sum = 0;
for (int i = 1; i < len; i++) {
sum += prices[i] > prices[i-1] ? prices[i] - prices[i-1] : 0;
}
return sum;
}
int[][] local = new int[len][k+1];
int[][] global = new int[len][k+1];
for (int i = 1; i < len; i++) {
int diff = prices[i] - prices[i-1];
for (int j = 1; j <= k; j++) {
local[i][j] = Math.max(global[i-1][j-1] + Math.max(diff, 0),
local[i-1][j] + diff);
global[i][j] = Math.max(global[i-1][j], local[i][j]);
}
}
return global[len-1][k];
}
}
2.
public class Solution {
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (n < 2) return 0;
if (k + k > n) {
int profit = 0;
for (int i = 1; i < n; i++)
if (prices[i] > prices[i-1])
profit += prices[i] - prices[i-1];
return profit;
}
int[][] dp = new int[k+1][n];
for (int i = 1; i <= k; i++) {
int max = -prices[0];
for (int j = 1; j < n; j++) {
dp[i][j] = Math.max(dp[i][j-1], prices[j]+max);
max = Math.max(max, dp[i-1][j]-prices[j]);
}
}
return dp[k][n-1];
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。