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. SQL注入漏洞知识总结

    目录: 一.SQL注入漏洞介绍 二.修复建议 三.通用姿势 四.具体实例 五.各种绕过 一.SQL注入漏洞介绍: SQL注入攻击包括通过输入数据从客户端插入或“注入”SQL查询到应用程序.一个成功的S ...

  2. 【bzoj4940】这是我自己的发明

    Portal --> bzoj4940 Solution (原题这题面到底是..怎么回事啊深深的套路qwq) 感觉自己对根号的算法还是很..没有感觉啊== 实际上这题和bzoj5016没有任何区 ...

  3. 初识python版本

    区别一: python2x:源码重复不规范. python3x:重新整理规范了源码. 区别二: python2x: 默认的编码方式ascii,显示中文需要首行添加:#  _*_ encoding: u ...

  4. source 导入文件

    有时候,phpmyadmin 导入  是有大小限制的: 只可以用sql命令的source来导入文件

  5. oracle,sqlserver,mysql常见数据库jdbc连接

    发现JDBC连接字符串总是容易忘记,特此整理一下常用的几种数据的连接 ORACLE: /** * ORACLE * */ public static Connection getOracleConne ...

  6. CSS3实现文本垂直排列

    最近的一个项目中要使文字垂直排列,也就是运用了CSS的writing-mode属性. writing-mode最初时ie中支持的一个属性,后来在CSS3中增添了这一新的属性,所以在ie中和其他浏览器中 ...

  7. UVA 11982 Fantasy Cricket

    https://vjudge.net/problem/UVA-11982 题意: 给出一个包含’U’, ‘D’, ‘E’的字符串, ’U’ 表示需要把这个字符向后移动, ’D’表示需要把这个字符向前移 ...

  8. 26 THINGS I LEARNED IN THE DEEP LEARNING SUMMER SCHOOL

    26 THINGS I LEARNED IN THE DEEP LEARNING SUMMER SCHOOL In the beginning of August I got the chance t ...

  9. User-Agent大全

    一.基础知识篇: Http Header之User-Agent User Agent中文名为用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA.它是一个特殊字符串头 ...

  10. CSS 定位相关属性 :position

    我们平时经常用margin来进行布局,但是遇到一些盒子不规律布局时,用margin就有点麻烦了,这个时候我们可以用position. position:参数 参数分析: 一.absolute: 相对父 ...