Best Time to Buy and Sell Stock

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 two transactions.

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

Example 1:

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

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
  Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
  engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

思路

这个题目有一系列的变形,唯一改变的是交易的次数,比如这题中限定的最多transaction是2,当然也可以限定为k。

解法还是dp,dp[k, i] 代表在price[i]之前 (price[0] ~ price[i])完成最多k个transaction所获得的最大利润,注意这里不是说以price[i]为结束,只是限定了k个transaction的大致范围,很有可能在k个transaction中是不包含price[i]的。那么得出:

dp[k, i] = max(dp[k, i-1], price[i] - price[ii] + dp[k-1, ii])       其中 ii在[0, i-1]范围内

   = max(dp[k, i-1], price[i] + max(dp[k-1, ii] - price[ii]))      其中 ii 在[0, i-1]范围内

dp[0, i] = 0

dp[k, 0] = 0

解决 k transaction 的代码如下,计算过程我看的有点蒙。

注意的是自低向上的计算过程,先计算 dp[1][1]~dp[1][n],也就是先从k=1,最多只有一笔交易的情况出发,然后去计算dp[2][1]~dp[2][n]......直到dp[k][1]~dp[k][n]。在计算dp[1][1]~dp[1][n]时,假设当前计算的是dp[1][i],会利用到dp[1][i-1],即第一笔交易是在0~i-1内的price完成,和price[i]没有关系。还要计算另一种情况,就是i计算在内,因为i是末位,所以只可能在price[i]卖出,但是和这个相对应的买入位不确定,所以要遍历i之前所有可能的买入位,即计算所有的 price[i]-price[ii],其中ii在0~i-1之间,那么之前的k-1笔交易只可能是在0~ii之内的,至于这里为什么包括ii,而不是ii-1,我猜是因为可以在同一天先卖后买,比如说我在第ii-1天先将手中持有的stcock卖出,再买入。

明白了上面之后,在计算dp[1][1]~dp[1][n],时如果确定了i,那么要计算所有的 price[i]-price[ii],取其price[i]-price[ii]+dp[0][ii-1]最大的一个,,ii在0~i-1之间,当i递增变为i+1时,又得计算所有的 price[i+1]-price[ii],其中ii在0~i之间,这样会重复计算的,所以要利用之前的计算结果,可以重复利用的是dp[0][i-1]-price[ii]这里,因为ii在0~i-1遍历,所以比如0~1,0~2以及0~3,计算0~3只需要计算dp[0][2]-price[2]的值,和之前0~2的计算结果直接相比即可。

感觉描述得有点乱,就是说在dp[i][j],i固定的情况下,dp[i-1][jj]-price[jj]的值由jj决定,当j增大时,比如从4到5,那么jj就是在 0~3和0~4中,这两个计算中0~3的计算是重复的,当j=4时我们只需要计算dp[1][3]-price[3]后再直接和上一次的结果比,再取较大的即可。这样我们在计算dp[1][1]到dp[1][n]时只需要计算开始处的dp[0][0]-price[0]再往后后项依赖前项递推即可。

/**
* dp[i, j] represents the max profit up until prices[j] using at most i transactions.
* dp[i, j] = max(dp[i, j-1], prices[j] - prices[jj] + dp[i-1, jj]) { jj in range of [0, j-1] }
* = max(dp[i, j-1], prices[j] + max(dp[i-1, jj] - prices[jj]))
* dp[0, j] = 0; 0 transactions makes 0 profit
* dp[i, 0] = 0; if there is only one price data point you can't make any transaction.
*/
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (n <= 1)
return 0; //if k >= n/2, then you can make maximum number of transactions.
if (k*2 >= n) {
int maxPro = 0;
for (int i = 1; i < n; i++) {
if (prices[i] > prices[i-1])
maxPro += prices[i] - prices[i-1];
}
return maxPro;
} int[][] dp = new int[k+1][n];
  
for (int i = 1; i <= k; i++) {
int localMax = dp[i-1][0] - prices[0];
for (int j = 1; j < n; j++) {
dp[i][j] = Math.max(dp[i][j-1], prices[j] + localMax);
localMax = Math.max(localMax, dp[i-1][j] - prices[j]);
}
}
return dp[k][n-1];
}

算法要点:

1. dp[i, j] represents the max profit up until prices[j] using at most i transactions。这个含义要注意,即到了第j天时最多用掉了i笔交易所获得的最大利润

2. 基于以上的定义,计算

dp[i, j] = max(dp[i, j-1], prices[j] - prices[jj] + dp[i-1, jj]) { jj in range of [0, j-1] }

时 jj 的范围每次都是从0 到j-1

3. localMax那块的计算逻辑

LeetCode解题报告—— Best Time to Buy and Sell Stock的更多相关文章

  1. 解题报告Best Time to Buy and Sell Stock with Cooldown

    题目 Say you have an array for which the ith element is the price of a given stock on day i. Design an ...

  2. 【一天一道LeetCode】#122. Best Time to Buy and Sell Stock II

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Say you ...

  3. 【LeetCode】188. Best Time to Buy and Sell Stock IV 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  4. 【LeetCode】309. Best Time to Buy and Sell Stock with Cooldown 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetc ...

  5. 【LeetCode OJ】Best Time to Buy and Sell Stock III

    Problem Link: http://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ Linear Time Solut ...

  6. 【leetcode】123. Best Time to Buy and Sell Stock III

    @requires_authorization @author johnsondu @create_time 2015.7.22 19:04 @url [Best Time to Buy and Se ...

  7. LeetCode 笔记23 Best Time to Buy and Sell Stock III

    Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of ...

  8. LeetCode OJ 123. Best Time to Buy and Sell Stock III

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  9. leetcode:122. Best Time to Buy and Sell Stock II(java)解答

    转载请注明出处:z_zhaojun的博客 原文地址 题目地址 Best Time to Buy and Sell Stock II Say you have an array for which th ...

随机推荐

  1. word----遇到问题-----word中插入的图片无法左对齐----格式按钮为灰色

    当我们在用word时,有时要插入图片,却发现,插入的图片只在中间位置,不能拖到左边,这时怎么办呢 主要是图层的高低原因导致的不能拖动. 这个时候我们只需要设置一下图片的图层类型即可. 对着图片右键在设 ...

  2. bzoj4010: [HNOI2015]菜肴制作(拓扑排序+贪心+堆)

    这题不是求最小字典序...撕烤了半个小时才发现不对劲T T 这题是能让小的尽量前就尽量前,无论字典序...比如1能在2前面就一定要在2前面... 显然是要先拓扑排序,让小的尽量前转化成让大的尽量往后丢 ...

  3. 数字表格(product)

    Portal -->broken qwq Description ​  求\(\prod\limits_{i=1}^n\prod\limits_{j=1}^m f[gcd(i,j)](mod\ ...

  4. Git入门指南

    git学习资源: Pro Git(中文版) Learn Git in your browser for free with Try Git. Git常用命令 Reference 常用 Git 命令清单 ...

  5. 流媒体协议之RTP详解20170921

    1.RTP介绍 实时传输协议RTP(Real-time Transport Protocol)是一个网络传输协议,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的,后在RFC35 ...

  6. duilib 修复padding属性导致其他控件自动计算宽高度错误的bug和导致自己宽高度错误的bug

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42950733          BUG 一:padding导致其他控件宽 ...

  7. net-speeder

    有的同学反映自己的搬瓦工速度慢,丢包率高.这其实和你的网络服务提供商有关.据我所知一部分上海电信的同学就有这种问题.那么碰到了坑爹的网络服务商,我们应该怎么办呢? duangduang~~~~~~有请 ...

  8. JVM调优总结:一些概念

    数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型.基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对象本身, ...

  9. HTML5文件上传器,纯脚本无插件的客户端文件上传器---Uploader 文件上传器类

    概述 客户端完全基于JavaScript的 浏览器文件上传器,不需要任何浏览器插件,但需要和jQuery框架协同工作,支持超大文件上传,其算法是将一个超大文件切片成N个数据块依次提交给服务 端处理,由 ...

  10. 【BZOJ】3039: 玉蟾宫 悬线法

    [题意]给定01矩阵,求最大全1子矩阵.n,m<=1000. [算法]动态规划(悬线法) [题解]★对于01矩阵中的任意一个全1极大子矩阵,都可以在其上边界遇到的障碍点处悬线到下边界的点x,则点 ...