牛客题解-NC134股票(无限次交易)

题目

假定你知道某只股票每一天价格的变动。

你最多可以同时持有一只股票。但你可以无限次的交易(买进和卖出均无手续费)。

请设计一个函数,计算你所能获得的最大收益。

示例1

输入:

1
[5,4,3,2,1]

输出:

1
0

tips:

1
由于每天股票都在跌,因此不进行任何交易最优。最大收益为0

示例2

输入:

1
[1,2,3,4,5]

输出:

1
4

tips:

1
2
第一天买进,最后一天卖出最优。中间的当天买进当天卖出不影响最终结果。最大收益为4
总天数不大于200000。保证股票每一天的价格在[1,100]范围内。

思路

分析

1
定义dp[i][0]表示第i+1天交易完之后手里没有股票的最大利润,dp[i][1]表示第i+1天交易完之后手里持有股票的最大利润。

当天交易完之后手里没有股票可能有两种情况,一种是当天没有进行任何交易,又因为当天手里没有股票,所以当天没有股票的利润只能取前一天手里没有股票的利润。一种是把当天手里的股票给卖了,既然能卖,说明手里是有股票的,所以这个时候当天没有股票的利润要取前一天手里有股票的利润加上当天股票能卖的价格。这两种情况我们取利润最大的即可,所以可以得到

1
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);

当天交易完之后手里持有股票也有两种情况,一种是当天没有任何交易,又因为当天手里持有股票,所以当天手里持有的股票其实前一天就已经持有了。还一种是当天买入了股票,当天能卖股票,说明前一天手里肯定是没有股票的,我们取这两者的最大值,所以可以得到

1
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);

动态规划的递推公式有了,那么边界条件是什么,就是第一天

1
2
如果买入:dp[0][1]=-prices[0];
如果没买:dp[0][0]=0;

有了递推公式和边界条件,代码很容易就写出来了

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.*;


public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算最大收益
* @param prices int整型一维数组 股票每一天的价格
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
if(prices == null || prices.length < 2) return 0;
int[][] dp = new int[prices.length][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < prices.length; i++){
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);
}
return dp[prices.length - 1][0];
}
}