Best Time to Buy and Sell Stock IV

题目等级:Hard

题目描述:

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.

Note:

You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Example 1:

Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.

Example 2:

Input: [3,2,6,5,0,3], k = 2
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.

  题意:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算所能获取的最大利润。最多允许完成k次交易,必须在再次购买前出售掉之前的股票。


解题思路(动态规划):

  股票怎么都买卖不完了。。。。

  本题是股票买卖系列的第四题,前面三道分别处理了一次交易、无数次交易、两次交易的情形,其主要思想就是动态规划,这里直接扩展到了任意次(k次),难度可以说是相当大了,自己没有什么思路,参考了网上的解答,这里做一个解释和记录吧。

  和前面三道一样,动态规划仍然是解决此题的思路,只不过这里的状态定义很复杂。

  这里定义两个变量,local和global分别表示全局最优和局部最优,定义如下:local[i][j]表示在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,此为局部最优。global[i][j]表示到达第i天时最多可进行j次交易的最大利润,此为全局最优。

  我们首先来看global,它代表全局最优,那么global[i][j] = max(local[i][j], global[i - 1][j]),这个相对好理解一些,是动态规划的常规用法,全局最优等于前一天的全局最优和当前的局部最优的较大者。

  而local的更新比较复杂,主要是注意local[i][j]表示的是最后一支股票在第i天卖出,也就是第 i 天卖第 j 支股票,这样的话有三种情况:

  • 之前已经将j次交易进行完了,最后一次是今天买,今天卖,相当于啥也没干,则 Local(i, j) = Global(i-1, j-1).
  • 第j次交易是昨天买的,第i天卖,则Local(i, j) = Global(i-1, j-1) + diff
  • 第j次交易是更早之前买的,第i天卖,则Local(i, j) = Local(i-1, j) + diff,也就是Local(i-1, j)代表最后一次交易第i-1天卖出,加diff就是说昨天不卖,留到今天卖。

  其中diff=prices[i]-prices[i-1]

  由此分析,可以得出local的递推公式:local[i][j] = max(global[i - 1][j - 1], local[i - 1][j]) + diff

  所以,总结起来,本题的解题思路是以下三个公式:

diff = prices[i] - prices[i - 1]
global[i][j] = max(local[i][j], global[i - 1][j])
local[i][j] = max(global[i - 1][j - 1], local[i - 1][j]) + diff

  根据这个分析,给出以下代码实现:

class Solution {
public int maxProfit(int k, int[] prices) {
if(prices==null || prices.length==0)
return 0;
int len=prices.length;
if(len<2||k<1)
return 0;
if(k>=len) //交易次数多于天数,可以按照无数次来直接解决
return getMax(prices);
int[] global=new int[k+1];
int[] local=new int[k+1];
for(int i=0;i<len-1;i++){
int diff=prices[i+1]-prices[i];
for(int j=k;j>=1;--j){ //为了取到上一次的global[j-1],需要从后往前遍历,否则会覆盖
local[j]=Math.max(global[j-1],local[j])+diff;
global[j]=Math.max(global[j],local[j]);
}
}
return global[k];
}
public int getMax(int[] prices){
int res = 0;
for (int i = 1; i < prices.length; ++i) {
if (prices[i] > prices[i - 1])
res += (prices[i] - prices[i - 1]);
}
return res;
}
}

  时间复杂度:O(n*k),空间复杂度:O(2k)

总结

  太难了。。。本题确实有相当的难度,如何确定状态和确定递推关系很复杂,另外代码实现中一位数组代替二维也是一个很好的解决办法。这也是买卖股票这些题目中最难的一道了,接下来还有两道相关的变形。

【LeetCode】188、买卖股票的最佳时机 IV的更多相关文章

  1. Java实现 LeetCode 188 买卖股票的最佳时机 IV

    188. 买卖股票的最佳时机 IV 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多 ...

  2. Leetcode 188.买卖股票的最佳时机IV

    买卖股票的最佳时机IV 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多笔交易(你必 ...

  3. leetcode 188. 买卖股票的最佳时机 IV

    参见 本题采用了第一列初始化后,从左侧向右开始递推的方式,但从上往下递推应该也成立,以后尝试一下 想写一个普适性的适用于n天交易k次持有j股的状态方程但是有问题:对于交易次数过多的情况数组会超出界限: ...

  4. Leetcode之动态规划(DP)专题-188. 买卖股票的最佳时机 IV(Best Time to Buy and Sell Stock IV)

    Leetcode之动态规划(DP)专题-188. 买卖股票的最佳时机 IV(Best Time to Buy and Sell Stock IV) 股票问题: 121. 买卖股票的最佳时机 122. ...

  5. 【力扣】188. 买卖股票的最佳时机 IV

    给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意:你不能同时参 ...

  6. [Leetcode][动态规划] 买卖股票的最佳时机IV

    一.题目描述 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多笔交易(你必须在再次购 ...

  7. LeetCode《买卖股票的最佳时机》系列题目,最详解

    目录 说在前面 引例:只能交易一次 一.动态数组定义 二.状态转移方程 三.初始化 四.优化 无限制买卖 一.动态数组定义 二.状态转移方程 三.初始化 四.优化 交易 2 次,最大利润? 一.动态数 ...

  8. lintcode:买卖股票的最佳时机 IV

    买卖股票的最佳时机 IV 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格. 设计一个算法来找到最大的利润.你最多可以完成 k 笔交易. 注意事项 你不可以同时参与多笔交易(你必须在再次 ...

  9. 每日一题-——LeetCode(121)买卖股票的最佳时机

    题目描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格.如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润.注意你不能在买入股票前卖出股票 ...

  10. Leetcode——121. 买卖股票的最佳时机

    题目描述:买卖股票的最佳时机 题目要求求解能获得最大利润的方式? 可以定一个二维数组 d [ len ] [ 2 ] ,其中d[ i ][ 0 ] 表示前i天可以获得的最大利润:d[ i ][ 1 ] ...

随机推荐

  1. Lambda学习总结(二)--Stream流

    一.Stream 流 1.1 概念 官方解释:可以支持顺序和并行对元素操作的元素集合. 简单来讲,Stream 就是 JDK8 提供给我们的对于元素集合统一.快速.并行操作的一种方式. 它能充分运用多 ...

  2. UVALive - 5695 The Last Puzzle (思维+区间dp)

    题目链接 题目大意:有n个按钮排成一条直线,你的任务是通过左右移动按下所有按钮,按钮如果一段时间没有被按下就会被弹开. 以下是我的推论(不一定正确): 直观地看的话,如果选择的是最优路径,那么路径的形 ...

  3. 我说CMMI之五:CMMI 4个等级的区别--转载

    我说CMMI之五:CMMI 4个等级的区别 了解CMMI的人都知道CMMI有5个等级,但是要将5个等级的区别真正说明白,说透彻不太容易.下面我们用一个表格概括之.表格中并没有1级,1级在CMMI中没有 ...

  4. Kendo UI for jQuery自定义小部件第一弹!不得不看的入门指南

    Kendo UI for jQuery最新试用版下载 Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support f ...

  5. 深浅拷贝(copy)

    目录 copy 模块 1.拷贝(赋值) 1). x为不可变数据类型 2). x为可变数据类型 3). 可变数据类型(比如列表)内,既有不可变元素,又有容器类型可变元素(比如列表) 2.浅拷贝 3.深拷 ...

  6. sql DATEDIFF函数使用

    date_part abbreviations year yy, yyyy quarter qq, q month mm, m dayofyear dy, y day dd, d week wk, w ...

  7. 计算机网络(十一),HTTP和HTTPS区别

    目录 1.SSL(Security Sockets Layer,安全套接层) 2.加密方式 3.HTTPS数据传输流程 4.HTTP和HTTPS的区别 5.HTTP真的很安全吗 十一.HTTP和HTT ...

  8. CSP-S2 游记

    CSP-S2 游记 & AFO 感想 Day0 早上考了一场式,非常简单,但是懒得写正解.230pts. 晚上听了一下WYQ大神的考前直播,写了一下树上倍增(我是不会告诉你我还写炸了) 与lu ...

  9. mybatis invalid bound statement (not found)

    Spring boot + Mybatis : Invalid bound statement (not found) 如果只在启动类上配置@MapperScan注解,默认只扫描和mapper接口同名 ...

  10. You Are Given a Decimal String...

    B. You Are Given a Decimal String... 这个题需要求出从某一个尾数 n 变为 m 所需要的 x 和 y 的最小个数(i+j) 那么就需要预处理出一个数组来存放这个值. ...