题目描述
给定一个数组prices, prices[i]表示第i天股票的股价,现在你可以在某一天买一次股票,在后面的另外一天再把股票卖了,那么中间的差价prices[j]-proces[i]就是你赚取的利润,求你能赚的利润的最大值。
举个例子:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.Not 7-1 = 6, as selling price needs to be larger than buying price.
分析思路
这种题应该用动态规划(dynamic planning,dp算法)做。动态规划就是求源问题规模较小时的情况,慢慢扩大规模,逐步求解。在上面的例子里,prices=[7,1,5,3,6,4],这是原问题的规模,那么比它规模较小的那个问题应该是prices=[7,1,5,3,6],并且[7,1,5,3,6,4]的求解依赖于[7,1,5,3,6],依次类推,推到最小的问题规模[7,1],因为数组最起码要有两个元素。
当[7,1]时,最大利润很明显=0
当[7,1,5]时,最大规模=5-1=4
当[7,1,5,3]时,最大规模=5-1=4
。。。
那么每种规模问题的解之间存在什么关系呢?
先定义几个表示方式。[7,1]时的问题的解,我们定义为dp[2],[7,1,5]的解,定义为dp[3],依次类推。
那么怎么根据dp[3]之前的解推导出dp[3],是动态规划最核心的问题。
这里dp[3]表示,数组长度为3时,买卖股票的最大利润。
按常识,dp[3] = max(dp[2], prices[2]-minPrice),这里的prices[2]表示第3天的股价。
按照这个公式,我们推一下。
先确定初始条件,dp[0]=dp[1]=0,当数组长度小于2时,利润为0。
dp[2]: [7,1]的时候,dp[2] = max(dp[1], prices[1]-minPrice) = max(0, 1-7) = 0;
dp[3]: [7,1,5]的时候,dp[3] = max(dp[2], prices[2]-minPrice) = max(0, 5-1) = 4;
dp[4]: [7,1,5,3]的时候,dp[4] = max(dp[3], prices[3]-minPrice) = max(4, 3-1) = 4;
dp[5]: [7,1,5,3,6]的时候,dp[5] = max(dp[4], prices[4]-minPrice) = max(4, 6-1) = 5;
dp[6]: [7,1,5,3,6,4]的时候,dp[6] = max(dp[5], prices[5]-minPrice) = max(5, 4-1) = 5;
代码
class Solution {
public int maxProfit(int[] prices) {
if (prices.length < 2){
return 0;
}
int currentMin = prices[0];
int[] dp = new int[prices.length+1]; //dp[i] = 0,初始化全部为0
for (int i = 2; i <= prices.length; i++){
dp[i] = Math.max(dp[i-1], prices[i-1]-currentMin);
currentMin = Math.min(currentMin, prices[i-1]);
}
return dp[prices.length];
}
}
优化的地方
在上面的例子里,我们维护了一个一维数组,空间复杂度为O(n),但是在实际的编码过程中,我们在求dp[i]的时候,依赖的那个dp[i-1]一定是前面所有dp[j], j<i的最大值。因此,我们可以不使用这样的一维数组,而仅仅使用一个变量来保存已经求得的dp中的最大值即可。
class Solution {
public int maxProfit(int[] prices) {
if (prices.length < 2){
return 0;
}
int currentMaxProfit = 0;
int currentMin = prices[0];
for (int i = 0; i < prices.length; i++) {
currentMin = Math.min(currentMin, prices[i]);
currentMaxProfit = Math.max(currentMaxProfit, prices[i]-currentMin);
}
return currentMaxProfit;
}
}