当前位置: 首页 > news >正文

leetcode-188 买卖股票4

题目

    给定一个数组表示股票每天的价格,最多交易k次,且手上最多只能拥有一支股票(即只能先卖出手上现有的股票再去购买新的股票),求最大的收益。 
    题目链接:买卖股票4 
    开始思路不清楚,参考了http://blog.csdn.net/dr_unknown/article/details/51939121 的解法。 
使用动态规划,先找清状态,题目中有两个主要变量天数,和交易次数,以及所要求的结果:最大的收益。那么可以构造状态dp[i][j],表示前i天最多交易j次获得的最大收益。 
    有了状态dp,可以找到递推公式:dp[i][j] = max{dp[i-1][j], dp[i-1][j-1] + prices[i] - prices[i-1]}:前i天进行j次的最大收益,等于前i-1天进行完最多j次交易的收益A和前i-1天进行完j-1次交易,且第i天进行最后一次交易的收益B的最大值。 
    但是这样有个问题,对于第二种情况,如果dp[i-1][j-1]中第j-1次交易是在第i-1天进行了卖出,那么 dp[i-1][j-1] + prices[i] - prices[i-1] 就相当于第j-1次交易是在第i天进行了卖出,最终相当于i天最多只进行了j-1次交易。 
    于是,需要细化状态,考虑使用状态 local[i][j]表示前i天最多进行j次交易,且最后一次卖出交易是在第i天完成,所获得的最大收益;global[i][j]表示前i天最多进行j次交易所获得的最大收益。 
于是有递归公式: 
local[i][j] = max{global[i-1][j-1] + max(prices[i] - prices[i-1], 0), local[i-1][j] + prices[i] - prices[i-1]} 
global[i][j] = max{local[i][j], global[i-1][j]}
 
    进一步的,状态第一维i只和i-1有关,可以进行空间压缩,将二维数组变成一维,于是有递推公式: 
local[j] = max{global[j-1] + max(prices[i] - prices[i-1], 0), local[j] + prices[i] - prices[i-1]} 
global[j] = max{local[j], global[j]}
 
但是需要注意j需要从高到低遍历,因为第i天交易j次的最优解依赖于第i-1天交易j-1次的最优解。 
    进行状态压缩时,数组的遍历方向很容易搞混,这是可以使用滚动数组,滚动数组一方面可以压缩空间,另一方面也不需要太过考虑数组的遍历方向。 
local[new_scroll][j] = max(global[old_scroll][j-1] + max(diff, 0), local[old_scroll][j] + diff); 
global[new_scroll][j] = max(local[new_scroll][j], global[old_scroll][j]);

实现

class Solution {
public:
	int maxProfit(int k, vector<int> &prices) {
	    int n = prices.size();
	    if(n <= 1)
	        return 0;
	    if(k >= n)
	        return maxProfit2(prices);
	    for(int i = 0; i < 2; i ++){
	        local[i].assign(k + 1, 0);
	        global[i].assign(k + 1, 0);
	    }
	    int old_scroll = 0, new_scroll;
	    for(int i = 1; i < n; i ++){
	        int diff = prices[i] - prices[i-1];
	        new_scroll = 1 - old_scroll;
	        for(int j = 1; j <= k; j ++){
	            local[new_scroll][j] = max(global[old_scroll][j-1] + max(diff, 0), local[old_scroll][j] + diff);
	            global[new_scroll][j] = max(local[new_scroll][j], global[old_scroll][j]); //注意这里 local 为new_scroll
	        }
	        old_scroll = new_scroll;
	    }
	    return global[new_scroll][k];
	}
	int maxProfit2(vector<int>& prices){
	    int result = 0;
	    int n = prices.size();
	    for(int i = 1; i < n; i ++){
	        if(prices[i] > prices[i-1])
	            result += (prices[i] - prices[i-1]);
	    }
	    return result;
	}
private:
    vector<int> local[2];
    vector<int> global[2];
};

 

相关文章:

  • [转]理解I/O Completion Port
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • 【iOS第三方框架】FMDB刚刚好
  • C#框架及概念
  • vue webpack 构建
  • 设计模式之观察者模式(c++)
  • codeforces 492E. Vanya and Field(exgcd求逆元)
  • tcp 重发 应用层重传
  • Log4j具体使用实例
  • ios8之后的界面旋转简单原理
  • 设计模式之桥接模式(Bridge模式)
  • jsdoc文档
  • ESXI虚拟化增加系统盘容量
  • php过滤textarea 中的换行符问题
  • Unity3D-光照贴图技术
  • 【css3】浏览器内核及其兼容性
  • ES学习笔记(12)--Symbol
  • Fabric架构演变之路
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • github指令
  • Java 最常见的 200+ 面试题:面试必备
  • Java,console输出实时的转向GUI textbox
  • Js基础知识(四) - js运行原理与机制
  • Laravel5.4 Queues队列学习
  • nginx 负载服务器优化
  • react-native 安卓真机环境搭建
  • 测试如何在敏捷团队中工作?
  • 大整数乘法-表格法
  • 关于extract.autodesk.io的一些说明
  • 理清楚Vue的结构
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 收藏好这篇,别再只说“数据劫持”了
  • 我看到的前端
  • 再谈express与koa的对比
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 《天龙八部3D》Unity技术方案揭秘
  • 阿里云API、SDK和CLI应用实践方案
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • # Panda3d 碰撞检测系统介绍
  • #LLM入门|Prompt#3.3_存储_Memory
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • $().each和$.each的区别
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (5)STL算法之复制
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (利用IDEA+Maven)定制属于自己的jar包
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转) ns2/nam与nam实现相关的文件
  • (转)socket Aio demo
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core 中插件式开发实现
  • .NET delegate 委托 、 Event 事件,接口回调