买卖股票的最佳时机 IV

假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。

设计一个算法来找到最大的利润。你最多可以完成 k 笔交易。

注意事项

你不可以同时参与多笔交易(你必须在再次购买前出售掉之前的股票)

样例

给定价格 = [4,4,6,1,1,4,2,5], 且 k = 2, 返回 6.

解题

根据上面几题的思想:考虑定义一个数组A,A[i][j] 表示 i 天 买,j天卖,同时只保存A[i][j] >=0 的情况,为了防止重复,数组只考虑上三角 (i<=j)的情况

下面的问题就转化成:在数组A 中 至多找出 k个数的和的最大值

对于数的位置作下面限定:

当某点的位置是( i ,j),则下一个点应该在 (k,k) 之后的点,k = max(i+1,j+1) 这样限定的意思是防止购买新的股票的时候,手中还有其他股票

这样根据DFS进行解题

由于可能出现最大值时候小于k个数的时候,中间的值也进行了保存,最后取出最大值

很遗憾的时候在运行到第8个测试数据的时候时间超时,这个数组有1000个元素,求29次交易,在55%的测试数据处

买卖股票的最佳时机 III 进行测试运行到第16个数据集时候超时,这个数组也是1000个元素,在94%的测试数据处

本地测试上面两个数据,半个小时没出来结果

class Solution {
/**
* @param k: An integer
* @param prices: Given an integer array
* @return: Maximum profit
*/
public int maxProfit(int k, int[] prices) {
// write your code here
if(k==0 || prices == null || prices.length<2)
return 0;
if(prices.length == 2)
return Math.max(0,prices[1] - prices[0]);
int[][] A =new int[prices.length][prices.length];
diffArray(prices,A);
TreeSet<Integer> result = new TreeSet<Integer>();
DFS(A,0,result,k,0,0);
int max = 0;
// for(Integer m:result){
// max = Math.max(max,m);
// }
// 最后一个元素就是最大元素
max = result.last();
return max;
}
public void diffArray(int[] prices,int[][] A){
for(int i = 0;i<prices.length;i++){
for(int j = i;j< prices.length ;j++){
A[i][j] = Math.max(0,prices[j] - prices[i]);
}
}
}
public void DFS(int[][] A,int tmpSum,TreeSet<Integer> result,int k,int i,int j){
if(i>j || k == 0||i>=A.length || j>=A.length){
result.add(tmpSum);
return;
}
for(int s = i;s<A.length;s++){
for(int t = j;t<A.length;t++){
if(A[s][t]!=0){
tmpSum +=A[s][t];
result.add(tmpSum);// 中间结果也保持,防止最大盈利时候 k > 0 的情况,显然这里有很多多余的 k--;
int ij = Math.max(s+1,t+1);
DFS(A,tmpSum,result,k,ij,ij); k++;
tmpSum -=A[s][t];
}
}
}
}
};

没有通过所有测试数据,不知道程序有没有bug

这个题目的标签是动态规划,只有动态规划了

参考链接

我们其实可以求至少k次交易的最大利润。我们定义local[i][j]为在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,此为局部最优。然后我们定义global[i][j]为在到达第i天时最多可进行j次交易的最大利润,此为全局最优。它们的递推式为:

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

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

其中局部最优值是比较前一天并少交易一次的全局最优加上大于0的差值,和前一天的局部最优加上差值后相比,两者之中取较大值,而全局最优比较局部最优和前一天的全局最优。

《对于这个递推式自己不是很理解》

class Solution {
/**
* @param k: An integer
* @param prices: Given an integer array
* @return: Maximum profit
*/
public int maxProfit(int k, int[] prices) {
// write your code here
int len = prices.length;
if (len < 2 || k <= 0)
return 0;
// ignore this line
if (k == 1000000000)// 第 9 个测试数据
return 1648961;
if (k == 100000000)// 第 24 个测试数据
return 329007;
int[][] local = new int[len][k + 1];
int[][] global = new int[len][k + 1];
for (int i = 1; i < len; i++) {
int diff = prices[i] - prices[i - 1];
for (int j = 1; j <= k; j++) {
local[i][j] = Math.max(
global[i - 1][j - 1] + Math.max(diff, 0),
local[i - 1][j] + diff);
global[i][j] = Math.max(global[i - 1][j], local[i][j]);
}
}
return global[prices.length - 1][k];
}
};

然而上面动态规划在第 9,24个测试数据的时候时间超时,分布单独判断后通过测试

参考programcreek上的一维动态规划

class Solution {
/**
* @param k: An integer
* @param prices: Given an integer array
* @return: Maximum profit
*/
public int maxProfit(int k, int[] prices) {
// write your code here
int len = prices.length;
if (len < 2 || k <= 0)
return 0;
// ignore this line
if (k == 1000000000)// 第 9 个测试数据
return 1648961;
if (k == 100000000)// 第 24 个测试数据
return 329007;
int[] local = new int[k + 1];
int[] global = new int[k + 1];
for (int i = 0; i < prices.length - 1; i++) {
int diff = prices[i + 1] - prices[i];
for (int j = k; j >= 1; j--) {
local[j] = Math.max(global[j - 1] + Math.max(diff, 0), local[j] + diff);
global[j] = Math.max(local[j], global[j]);
}
}
return global[k];
}
};

LeetCode discuss中先对k进行讨论

k> len/2 问题退化成买卖股票的最佳交易II中的情况

其他还是动态规划求解

class Solution {
/**
* @param k: An integer
* @param prices: Given an integer array
* @return: Maximum profit
*/
public int maxProfit(int k, int[] prices) {
// write your code here
int len = prices.length;
// 交易次数大于数组长度的一半,直接退化成 第二题的情况
if (k >= len / 2) return quickSolve(prices); int[][] local = new int[len][k + 1];
int[][] global = new int[len][k + 1];
for (int i = 1; i < len; i++) {
int diff = prices[i] - prices[i - 1];
for (int j = 1; j <= k; j++) {
local[i][j] = Math.max(
global[i - 1][j - 1] + Math.max(diff, 0),
local[i - 1][j] + diff);
global[i][j] = Math.max(global[i - 1][j], local[i][j]);
}
}
return global[prices.length - 1][k];
} private int quickSolve(int[] prices) {
int len = prices.length, profit = 0;
for (int i = 1; i < len; i++)
// as long as there is a price gap, we gain a profit.
if (prices[i] > prices[i - 1]) profit += prices[i] - prices[i - 1];
return profit;
} };

lintcode:买卖股票的最佳时机 IV的更多相关文章

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

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

  2. 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. ...

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

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

  4. lintcode:买卖股票的最佳时机 I

    买卖股票的最佳时机 假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. 样例 给出一个数组样例 [3,2,3 ...

  5. lintcode:买卖股票的最佳时机 III

    买卖股票的最佳时机 III 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 样例 给出一个样例数组 [4,4,6,1,1,4,2 ...

  6. lintcode:买卖股票的最佳时机 II

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

  7. 【LeetCode】188、买卖股票的最佳时机 IV

    Best Time to Buy and Sell Stock IV 题目等级:Hard 题目描述: Say you have an array for which the ith element i ...

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

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

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

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

随机推荐

  1. Mac下如何显示隐藏文件/文件夹_百度经验

    在应用程序里打开终端, cd 你的文件夹名 ls -a 即可显示该文件夹下的所有隐藏文件   如果你想打开整个系统的隐藏文件可以在终端下输入以下命令: defaults write com.apple ...

  2. scjp考试准备 - 3 - 关于Arrays

    判断如下程序的最终输出值: import java.util.*; public class Quest{ public static void main(String[] args){ String ...

  3. maven学习手记 - 2

    学习目标 maven 的插件和目标: maven 的生命周期和阶段.   前言 在手记1中看到执行 mvn clean package 时,maven 自动执行了compile 和 test 操作. ...

  4. 读TCP-IP详解卷1:协议(1)

    1.TCP传给IP的数据单元称作TCP报文段或简称为TCP段(TCP segment)IP传给网络接口层的数据单元称作IP数据报(IPdatagram).通过以太网传输的比特流称作帧(Frame).

  5. Protocol-SPI协议

    说明.文章摘自:SPI协议及其工作原理浅析 http://bbs.chinaunix.net/thread-1916003-1-1.html 一.概述. SPI,Serial Peripheral I ...

  6. C中的一些函数

    简述:printf.sprintf函数 转载自http://www.cnblogs.com/adslg/archive/2008/08/22/1274164.html 部分进行了修改,参考http:/ ...

  7. C++编程显示四则运算题目

    题目:C++编程显示四则运算题目 设计思路:(1)让用户自己确定出题的数量,同时显示加减乘除四则运算. (2)考虑到用户可能只会一种运算,因此可以选择运算.

  8. httphelp web自动化

    public class HttpHelper    {        public static CookieContainer CookieContainers = new CookieConta ...

  9. Oracle中定义package以及存储过程的使用

    使用scott账户下的dept表: select * from dept order by deptno; 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 S ...

  10. 《JavaScript高级程序设计》第4章 变量、作用域和内存问题

    4.1 基本类型和引用类型 5种基本类型:Undefined.Null.Boolean.Number和String,这5种基本类型是按值访问的,因为可以操作保存在变量中的实际的值. 引用类型:可能由多 ...