通用问题
- 可以进行K次交易
- 股票必须先买后卖
class Solution {
public int maxProfit(int k, int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
//k >= nums.length / 2, 可以理解为无限次
if (k >= prices.length / 2) {
return noLimit(prices);
}
int len = prices.length;
//设置持有状态和卖出状态
int[][] unhold = new int[k + 1][len];
int[][] hold = new int[k + 1][len];
for (int i = 1; i <= k; i++) {
unhold[i][0] = 0;
hold[i][0] = -prices[0];
for (int j = 1; j < len; j++) {
unhold[i][j] = Math.max(unhold[i][j - 1], hold[i][j - 1] + prices[j]);
hold[i][j] = Math.max(hold[i][j - 1], unhold[i - 1][j - 1] - prices[j]);
}
}
return Math.max(unhold[k][len - 1], hold[k][len - 1]);
}
private int noLimit(int[] prices) {
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] >= prices[i - 1]) {
profit += prices[i] - prices[i - 1];
}
}
return profit;
}
}
Tips
如果K >= nums.length / 2, 可以等价为无限买卖…
这里的核心是unhold[k…][i…]和hold[k…][i…]代表当前的状态是持有还是卖出, 其中从unhold->hold或者从hold->unhold可以看做进行了1次交易, 由于股票是先买后卖, 为了不重不漏,这里把从unhold->hold视作1次交易…
hold[i][j] = Math.max(hold[i][j - 1], unhold[i - 1][j - 1] - prices[j]);
买卖一次
##问题描述:
最好的时间买入于卖出股票。题目给出一串数组,其中第i个元素表示第i天股票的价格,你要做的事情是在这个数组中给出的股票价格中,找到一个最低价买进和最高价卖出以获得最大收益。但是最多只能做一次交易(买股票和卖股票),最后返回所获的最大利润。
##Ex:
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)
Input: [7, 6, 4, 3, 1]
Output: 0
In this case, no transaction is done, i.e. max profit = 0.
###例子解读:
对于第一个实例,我们在1的时候买进在6的时候卖出,获得最大利润5。
对于第二个实例,我们既不买也不卖,最大利润为0。
##解法一:
###思路
:这道题需要每个元素都派上用场,找到一组最小值和最大值,本质上来说是个动态规划问题。先让第一元素是最小值,然后逐个遍历,比最小值大则计算利润是否大于当前利润,比最小值小则将最小值赋给当前元素,最后返回最大利润。这里的最小值和利润都是动态的。
###Code:
public class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0){
return 0;
}
int max = 0 , min = prices[0];
int profit = 0;
for(int i = 1; i < prices.length; i++){
if(prices[i] < min){
min = prices[i];
}
else{
if(prices[i] - min > profit){
profit = prices[i] - min;
}
}
}
return profit;
}
}
##彩蛋:
一直觉得这个问题可以用纯粹的DP来解,而且这个问题是个很有趣的问题,等研究过DP后,在CSDN上和个人博客上分享