题记:在求最大最小值的类似题目中,递推思想的奇妙之处,在于递推过程也就是比较求值的过程,从而做到一次遍历得到结果。

LeetCode 上面的这三道题最能展现递推思想的美丽之处了。

题1 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.

分析:

我们已经知道股票每天的价格,求一次买卖的最大收益。

怎么解?最大值减最小值?肯定不行,因为买必须在卖之前。

简单的递推思想就可以解决

对于1-n天的价格序列,假设maxProfit[i] (0 < i < n)表示第i天卖出时,所获得的最大收益。那么我们要求的值其实就是数组maxProfit[n] n个元素中的最大值。

那么maxProfit[i]如何求?因为卖的天已经确定,所以只要算出1到i 天 中哪一天价格最低,作为买的时间即可。

根据递推思想,要求1到i 天 中哪一天价格最低,我们只需要比较 price[i] 和 1到i-1天内的最低价格,然后取较小值即可。

同样,最后的结果是求maxProfit[n]中的值,我们也可以把求最大值的过程放到遍历中,每次求出 maxProfit[i],我们将它和 maxProfit[0]到maxProfit[i-1] 中选出的最大值max比较,然后更新max即可。

因为比较的过程被放到了遍历的过程中,所以虽然使用递推思想,但是一次遍历就可以实现这个思想。

代码:

class Solution {
public:
int maxProfit(vector<int> &prices) {
if(prices.size() == ) return ;
int maxPrifit = -; //存储最大利润
int min = ; //存储最小价格
vector<int>::iterator i = prices.begin();
vector<int>::iterator end = prices.end();
for(; i < end; ++i){
if(min > (*i)) min = (*i);
if(maxPrifit < ((*i) - min))
maxPrifit = ((*i) - min);
}
return maxPrifit;
}
};

题2 Best Time to Buy and Sell Stock II

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 as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

分析:

更改的地方是可以多次买卖,但是买必须在卖前。

其实这道题才是三题中最简单的一道。

思路就是“逢涨就买,逢跌就卖”。炒股的最基本道理,只有在已经知道所有股票价格的前提下才能精确地实现这句话 ==

代码:

class Solution {
public:
int maxProfit(vector<int> &prices) {
if(prices.size() <= ) return ;
int buy = -; int profit = ;
vector<int>::iterator i = prices.begin();
vector<int>::iterator end = prices.end();
for(;i != end; ++i){
if((i+) != end && *(i+) > *i && buy < ) buy = (*i);
if(((i+) == end || *(i+) < *i) && buy >= ){
profit += (*i - buy);
buy = -;
}
}
return profit;
}
};

题3 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 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 (ie, you must sell the stock before you buy again).

分析:
题1的变种,可以买卖两次,但是不能重叠。

我的第一反应自然是分而治之,i = 1 to n,然后分别循环计算prices[1~ i], prices[i ~n] 的最大利润,相加,求出和的最大值。时间复杂度是实打实的 O(n2)。

稍微改进一些,就是我们在计算prices[1~ i]的时候,可以使用递推,这样思路就成了,在题1的代码基础上,每次算完prices[1~ i]的最小值,紧接着用一个循环 计算prices[i ~n] 的最大值。这样prices[1~ i]的最大利润计算和 i = 1~n的迭代合并,只有一个子循环, 一定程度上减小时间复杂度,时间复杂度成了 (n-1) + (n-2) + .. + 1,但依然是 O(n2)

实际上可以将复杂度减小到 O(n),这种方法会需要额外的 O(n)空间,但在一般编程领域,如果O(n)的空间能换来时间上减小一个数量级,还是相当好的。

我们先考虑一次买卖prices[1 ~ i] (0 < i < n)的最大利润,这就和题1一样,所不同的是,我们将值存入 firstMaxPro数组,而不是求出总的最大利润。

注意这里的firstMaxPro[n]数组和题目1中maxProfit[n]数组功能是不一样的。maxProfit[i] 表示一定在 i 天卖出的前提下,1~i天的最大利润。firstMaxPro[i]表示1~i天的最大利润,卖出可以在1~i天的任何时候。

接着,我们再做一次遍历,这一次遍历,从n 到 1,为的是将第二次买卖考虑进去,在求第二次买卖的最大利润的同时,就可以加上 firstMaxPro[n]中的对应值,然后求出总和最大。返回这个最大的总和即可。

两次n循环,时间复杂度O(n)

代码:

class Solution {
public:
int maxProfit(vector<int> &prices) {
if(prices.size() <= ) return ;
int* firstMaxPro = new int[prices.size()];
int curMin = ;
int curMaxPro = -;
for(int i = ; i < prices.size(); ++i){
if(curMin > prices[i]) curMin = prices[i];
if(curMaxPro < (prices[i] - curMin)){
curMaxPro = (prices[i] - curMin);
}
firstMaxPro[i] = curMaxPro;
} //从尾到头遍历
int MaxPro = -; //总的最大利润
int curMax = -; //第二段区间上的最大价格
for(int j = prices.size()-; j >= ; --j){
if(curMax < prices[j]) curMax = prices[j];//第二次买卖的最大利润就等于curMax - prices[j]
if(MaxPro < (firstMaxPro[j] + curMax - prices[j])){
MaxPro = (firstMaxPro[j] + curMax - prices[j]);
}
} return (MaxPro > ? MaxPro : );
}
};

结语

这三道题其实都不难,都是递推思想的一些演变。但是这三道题可以很典型地体现递推的核心思想和其优势:将比较和择优的过程和递推过程合并,从而只需要单次遍历,在O(n)内获得结果。

[LeetCode] 递推思想的美妙 Best Time to Buy and Sell Stock I, II, III O(n) 解法的更多相关文章

  1. LeetCode之“动态规划”:Best Time to Buy and Sell Stock I && II && III && IV

    Best Time to Buy and Sell Stock I 题目链接 题目要求: Say you have an array for which the ith element is the ...

  2. LeetCode:Best Time to Buy and Sell Stock I II III

    LeetCode:Best Time to Buy and Sell Stock Say you have an array for which the ith element is the pric ...

  3. leetcode day6 -- String to Integer (atoi) &amp;&amp; Best Time to Buy and Sell Stock I II III

    1.  String to Integer (atoi) Implement atoi to convert a string to an integer. Hint: Carefully con ...

  4. [Leetcode][JAVA] Best Time to Buy and Sell Stock I, II, III

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

  5. Best Time to Buy and Sell Stock I,II,III [leetcode]

    Best Time to Buy and Sell Stock I 你只能一个操作:维修preMin拍摄前最少发生值 代码例如以下: int maxProfit(vector<int> & ...

  6. [LeetCode]题解(python):123-Best Time to Buy and Sell Stock III

    题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ 题意分析: 和上题类似,array[i]代表第i天物品 ...

  7. [LeetCode]题解(python):122-Best Time to Buy and Sell Stock II

    题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 题意分析: 和上题类似,给定array,代表第i天物品i ...

  8. [LeetCode]题解(python):121-Best Time to Buy and Sell Stock

    题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 题意分析: 给定一个数组,代表array[i] 代表第i天的价 ...

  9. [leetcode]_Best Time to Buy and Sell Stock I && II

    一个系列三道题,我都不会做,google之答案.过了两道,第三道看不懂,放置,稍后继续. 一.Best Time to Buy and Sell Stock I 题目:一个数组表示一支股票的价格变换. ...

随机推荐

  1. HADOOP/HDFS Essay

    HDFS架构 the core of HADOOP/distributed systems is storeage(HDFS) and resource manager(YARN) for compu ...

  2. NMAP-主机扫描

    1.全面扫描 2.扫描指定段 3.ping扫描 只进行ping操作,十分隐蔽 4.无ping扫描 适用于防火墙禁止ping 5.TCP SYN扫描 6.TCP ACK扫描 7.UDP扫描 8.ICMP ...

  3. 十四:Using CGroups with YARN

        Cgroups可以控制linux 上应用程序的资源(内存.CPU)使用,yarn可以使用Cgroups来CPU使用.Cgroups的配置,在yarn-site.xml中设置: 1)启用Cgro ...

  4. Median Weight Bead(最短路—floyed传递闭包)

    Description There are N beads which of the same shape and size, but with different weights. N is an ...

  5. Thunder团队——事后诸葛亮会议

    小组名称:Thunder 项目名称:爱阅APP 小组成员:王航 李传康 代秋彤 邹双黛 苗威 宋雨 胡佑蓉 杨梓瑞 一.设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型 ...

  6. 20145214 《Java程序设计》第7周学习总结

    20145214 <Java程序设计>第7周学习总结 教材学习内容总结 时间的度量 格林威治标准时间(GMT),现已不作为标准时间使用,即使标注为GMT(格林威治时间),实际上谈到的的是U ...

  7. UBUNTU如何安装tar.gz版的flash

    adobe flash player的官方下载页面为:https://get.adobe.com/cn/flashplayer/ 不过近期通过APT方式以及ubuntu的软件中心都安装不了flashp ...

  8. lintcode-153-数字组合 II

    153-数字组合 II 给出一组候选数字(C)和目标数字(T),找出C中所有的组合,使组合中数字的和为T.C中每个数字在每个组合中只能使用一次. 注意事项 所有的数字(包括目标数字)均为正整数. 元素 ...

  9. 火狐浏览器(FireFox)安装Flash插件失败处理方法

    最近不知道怎么了,总是嫌弃IE,可能是被网络流量监测的网址给搞得了,弄了火狐浏览器,也安装了猎豹,这里不对浏览器做评价 好多朋友安装好火狐(FireFox)的时候发现之前不是有装IE的Flash播放插 ...

  10. .NET环境下,通过LINQ操作SQLite数据库

    //对应数据库中的某个表 [Table(Name = "main.Student")]    public class Student    {        [Column(Na ...