leetcode121 Best Time to Buy and Sell Stock
leetcode#121 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.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Example 1:
123456 >Input: [7, 1, 5, 3, 6, 4]>Output: 5>>max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)>>
>
Example 2:
12345 >Input: [7, 6, 4, 3, 1]>Output: 0>>In this case, no transaction is done, i.e. max profit = 0.>
解释
这是一个应用问题,关于股票买卖。
给定一个数组,数组元素第i位表示的是:第i天的股票价格。现在允许进行的股票买卖操作是:
- 只能进行一次买和一次卖——获得利润为卖出价格减去买进价格;
- 不买不卖——利润为0。
现在需要找到最大的利润(如果不买不卖,返回利润为0).
理解
这是一道可能可以使用暴力解法解决的问题(看限制条件,有可能暴力解法会遇到TLE的限制),所以更优的解法应该倾向于动态规划算法——将原问题划分成多个子问题,然后各个击破,最终汇总结果。
我的解法
解法一:暴力解法(遇到TLE限制)
|
|
解法二:动态规划
动态规划算法,需要先定义子问题的表达式——定义得好,有利于后续构建整体的DP算法。思路如下:
利用maxProfit(int[] A, int i)
表示A[0:i]
前i个元素中,所有A[j] - A[i],(j > i)
结果的最大值——即子问题的定义,所以可以得到递归表达式:maxProfit(A, i) = maxProfit(A, i-1) > (A[i] - minVal) ? maxProfit(A, i -1) : (A[i] - minVal)
。之后,就可以对递归表达式进行细化(根据问题的大小):是用全局变量存储,还是实实在在地使用递归方式求解。
其中,变量的含义是:
maxPro
,全局最优值,即全局的最大利润值;minVal
存储遍历过程中的最小值,因为是“先买后卖”,所以只需要将后续获取第i个数组元素减去minVal
,就可以得到第i天卖出股票所获得的利润,再与maxPro
相比较即可得到全局最优值。
|
|
解法二改进版:
之前一个版本中,不论minVal
与prices[i]
的大小关系如何,都会进行一长串的三元操作符比较过程,相当消耗资源。于是,改进版中将三元操作符装进了条件语句中,RunTimeBeat从9%提升到了44%。
|
|
大神解法
解法一:思路基本相同。
|
|
解法二:
该解法中提到了一个算法——Kadane’s Algorithm。
上述解法都是针对数组值大于等于0的情况(因为股价不可能为负数),如果对于任意场景,特别是数组元素为负数时,上述解法将会出现问题。
而Kadane’s Algorithm提供了一种针对Max Subarray问题的普适性解决方法:
maxCur
,将当前的maxCur
值与数组相邻两个元素之间的差值 进行相加,注意,这里的加和值需要大于0才能作为新的maxCur
值保存,否则归零——原因为:假设[...,x,y,z,...]
有三个相邻元素,如果(y-x)+(z-y)<0
即y-x <y-z
,说明z<x
,所以z
是当前遍历到的最小值,如果后续有较大的数W
,那么也会满足W-z>W-x
;maxSoFar
,保存全局最优值。
如此一来,即使数组元素有负数,也可以完成Max Subarray问题的求解。
|
|
总结
- 关于动态规划的问题,暴力解法一般也都可以使用,所以这种题型一般都会对暴力解法设置限制条件,比如TLE;
- 了解动态规划的思想是很有必要的,除了解决算法问题,动态规划可以为解决其他复杂问题提供一种简化和切入的思路,尝试定义子问题的表达式,不断简化子问题的表达式,也许就可以从中发现一些规律,从而推广到整体问题;
- 关于Max Subarray问题,Kadane’s Algorithm(也属于动态规划算法)已经将其完美解决。
原文地址:https://www.cnblogs.com/dajunjun/p/11699422.html
- 暑假集训之专题----拓扑排序题解
- 李沐:从头开始介绍机器学习,眼花缭乱的机器学习应用
- hdu------2488Tornado(几何)
- nyoj------203三国志
- nyoj 115------城市平乱( dijkstra // bellman )
- hdu----(1847)Good Luck in CET-4 Everybody!(简单巴什博奕)
- hdu----(3118)Arbiter(构造二分图)
- hdu----(1528)Card Game Cheater(最大匹配/贪心)
- hdu-----(1507)Uncle Tom's Inherited Land*(二分匹配)
- hdu----149850 years, 50 colors(最小覆盖点)
- hdu------1281 棋盘游戏(最小覆盖点)
- hdu-----(1179)Ollivanders: Makers of Fine Wands since 382 BC.(二分匹配)
- hdu-----(1151)Air Raid(最小覆盖路径)
- hdu-----(1150)Machine Schedule(最小覆盖点)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 后台登录微信并定时发送消息,消息包括农历、阴历、天气;自动监测是否断线,支持邮箱发送二维码登录;适合于挂在服务器上运行
- 《剑指offer》第八天:二叉树的下一个结点
- 基于python和OpenCV构建智能停车系统
- nvm管理工具
- 基于OpenCV的图像卡通化
- shadertoy绘图
- 单基因生信分析流程(6)单基因相似性分析
- 三阴性乳腺癌提取和分析
- 一日一技:更友好的格式化数据提取方案
- 『深度应用』YoloV5 RTX2080Ti TensorRT与PyTorch速度对比
- 0797-使用HDP或CDP的Atlas采集CDH6的元数据和血缘
- 现代通信理论与新技术 PPT笔记整理
- 找找规律——LeetCode题目6:Z字形变换
- 给你点信心——LeetCode题目7:整数反转
- Python -二叉树 创建与遍历算法(很详细,转自国外教程)