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.優化
Given an example [3,2,3,1,2], return 1code
只有一次交易,那麼將prices[]數組循環一次,每次循環更新prices[]
歷史最小值,並與當日價格相減獲得當日利潤,同步更新profit最大值。ip
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; } }
Say you have an array for which the i
th element is the price of a given stock on day i.element
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).同步
Given an example [2,1,2,0,1], return 2it
能夠有無限次交易,那麼在全部股票上漲的區間都進行交易。io
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; } }
Say you have an array for which the ith element is the price of a given stock on day i.class
Design an algorithm to find the maximum profit. You may complete at most two transactions.循環
Given an example [4,4,6,1,1,4,2,5], return 6.
買賣股票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]
,獲得收益最大值。
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; } }
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.
Given prices = [4,4,6,1,1,4,2,5], and k = 2, return 6.
首先分析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]
最後取上述兩種狀況的較大值。
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]; } }
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]; } }