leetCode刷题归纳-Array(Best Time to Buy and Sell Stock I&II&III)

来源:互联网 发布:matlab 矩阵色块图 编辑:程序博客网 时间:2024/06/06 23:59

最近因为准备面试,一直在leetcode上面刷题,在刷题的同时也会在有道云笔记上简单写一下个人体会,不足之处就是大部分的笔记都比较乱,没有系统的总结一些相似的题型和解法。正好林老师的算法课要求每周选择一个题目写一下解题心得,在这里也对之前做过的一些题目进行归纳整理,在巩固所学的同时也方便和大家分享讨论。

Best Time to Buy and Sell Stock I&II&III

选择的题目是股票买卖问题,这个问题是一个有扩展性的array问题,随着限定条件的增多延伸出不同的处理方法,三个题目的前提条件都是:

Say you have an array for which the ith element is the price of a given stock on day i.
大意就是说类似于这样的Input: [7, 1, 5, 3, 6, 4]


121.Best Time to Buy and Sell Stock 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.

只能做一次交易,思路就是在扫描所有的数字时,同时记录minPrice(当前扫描到的最小值)以及maxPro(当前所能获取到的最大利润),时间复杂度是O(n),非常简单。代码如下:

class Solution {public:    int maxProfit(vector<int>& prices) {        int maxPro=0;        int minPrice=INT_MAX;        for(int i=0;i<prices.size();i++){            minPrice=min(minPrice,prices[i]);            maxPro=max(maxPro,prices[i]-minPrice);        }        return maxPro;    }};

122.Best Time to Buy and Sell Stock II

本题限定条件是

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) {        int res=0;//以后像这样的后面有累加操作的值,一定记得在定义的时候赋初值以免出现问题        for(int i=1;i<prices.size();i++)                res+=max(prices[i]-prices[i-1],0);        return res;    }};

123.Best Time to Buy and Sell Stock III

本题限定条件是

Design an algorithm to find the maximum profit. You may complete at most two transactions.

最多只能做两次交易,另外在买第二只股票之前第一只必须出售,那么复杂的地方就显现出来了,到底是做一次交易还是做两次交易?结合代码分析:

class Solution {public:    int maxProfit(vector<int>& prices) {        int sell1 = 0, sell2 = 0, buy1 = INT_MIN, buy2 = INT_MIN;        for (int i = 0; i < prices.size(); i++) {            buy1 = max(buy1, -prices[i]);            sell1 = max(sell1, buy1 + prices[i]);            buy2 = max(buy2, sell1 - prices[i]);            sell2 = max(sell2, buy2 + prices[i]);        }        return sell2;    }};

我们假设在第i天,buy1代表第一次出手,sell1代表第一次抛售后的利润,假设一开始没有钱,buy1设为负值,sell1=price[i]+buy1(实际上为负值),我们总是希望能够以最低的价格买入,然后以最高的价格抛出,所以可以得到:

buy1 = max(buy1, -prices[i]);sell1 = max(sell1, buy1 + prices[i]);

同样地,在购买第二只股票的时候,考虑到之前已经进行过一次交易,可以得到:

buy2 = max(buy2, sell1 - prices[i]);sell2 = max(sell2, buy2 + prices[i]);

在举例验证的时候,可以发现sell1实际上代表当前状态下单次交易(不一定是首次交易)可以获得的最大利润,sell2代表两次交易累计可以获取的最大利润。例如对于数组[3,5,1,7],分析可以得到:

nums[i] buy1 sell1 buy2 sell2 3 -3 0 -3 0 5 -3 2 -3 2 1 -1 2 1 2 7 -1 6 1 8

观察发现buy1和buy3发生变化的是第一天和第三天,这说明分别在第一天和第三天购买可以获得最大利润,其他情况下同理。
回想一下这个问题,实际上就是求出array中nums[i]-nums[j] (i>j) 的最大和第二大之和(因为买第二只股票前一定要卖了第一只),所以通过遍历搜索(整个数列中最大的差值)+递归(数列中不包含最大差值的范围)的方式也能够得到结果,按照这个思路的话代码很简单在这里就不贴出来了。

0 0
原创粉丝点击