leetcode刷题记录(买卖股票的最佳时机系列问题)

开始逐步拾起C++,故以后的刷题,全用python和C++两种语言实现。

一、买卖股票的最佳时机 I

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

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

分析:第一题,相对简单,只能有一次交易。刚看到第一反应可能是遍历两次,找出所有的利润,选个最大的,意料之中,复杂度O(n^2)肯定超时。在一次遍历中,可以记录最小值,同时记录对应的利润即可。

python实现:

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices)<2:
            return 0
        profit = 0
        minprice = prices[0]
        for i in prices:
            minprice = min(i,minprice)
            profit = max(i-minprice,profit)
        return profit

C++实现:

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

二、买卖股票的最佳时机 II

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

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

示例 2:

输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

分析:不限制交易次数,其实看起来比 I 还要简单,可以直接一次遍历,把后一项大于前一项时,两者差值相加即可。

python实现:

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        temp = prices[0]
        profit = 0
        for i in prices:
            if i > temp:
                profit = profit + i - temp
            temp = i
        return profit

C++实现:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.empty())
        {
            return 0;
        }
        int temp = prices[0];
        int profit = 0;
        for(int i=0; i<prices.size();i++)
        {
            if (prices[i] - temp > 0)
            {
                profit = profit + prices[i] - temp;
            }
            temp = prices[i];
        }
        return profit;
    }
};

 三、买卖股票的最佳时机 III

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [3,3,5,0,0,3,1,4]
输出: 6
解释: 在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
     随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

示例 2:

输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。   
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入: [7,6,4,3,1] 
输出: 0 
解释: 在这个情况下, 没有交易完成, 所以最大利润为 0。

分析:此题加深了难度,限制了建议次数不大于2。最开始的想法是二分,遍历所有值作为二分点,分成左右两部分,分别求利润再求和,最后取最大,时间复杂度O(N^2),结果在倒数第二个评测时超时。优化一下,可以先从前往后遍历,按照 I 中的思路,将遍历到的每个值对应的最大利润存在一个列表中,然后从后往前遍历,在求此时的最大利润时,同时加上数组中的对应值,再取最大,即为所求。

python实现(二分,超时):

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        profit = 0
        for i in range(len(prices)):
            minprice1 = prices[0]
            profit1 = 0
            minprice2 = prices[i]
            profit2 = 0
            for m in range(0,i):
                minprice1 = min(prices[m],minprice1)
                profit1 = max(profit1,prices[m]-minprice1)
            for n in range(i,len(prices)):
                minprice2 = min(prices[n],minprice2)
                profit2 = max(profit2,prices[n]-minprice2)
            profit = max(profit,profit1+profit2)
        return profit

python实现:

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices)<2:
            return 0
        minprice = prices[0]
        maxprice = prices[len(prices)-1]
        profit1 = 0
        profit2 = 0
        profit = 0
        a = []
        for m in range(0,len(prices)):
            profit1 = max(profit1,prices[m]-minprice)
            minprice = min(prices[m],minprice)
            a.append(profit1)
        for n in range(len(prices)-2,-1,-1):
            maxprice = max(prices[n],maxprice)
            profit2 = max(profit2,maxprice-prices[n])
            profit = max(profit,a[n]+profit2)
        return profit

C++实现:

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        if(prices.empty())
            return 0;
        int minprice = prices[0];
        int maxprice = prices[prices.size()-1];
        int profit1 = 0;
        int profit2 = 0;
        int profit = 0;
        vector<int> a;
        for(int i = 0; i < prices.size(); i++){
            profit1 = max(profit1, prices[i] - minprice);
            minprice = min(minprice, prices[i]);
            a.push_back(profit1);
        }
        for(int i = prices.size() - 2; i >= 0; i--){
            maxprice = max(maxprice, prices[i]);
            profit2 = max(profit2, maxprice - prices[i]);           
            profit = max(profit,profit2 + a[i]);
        }
        return profit;
    }

};

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值