LeetCode 买卖股票的合适时间

最近在看贪心算法及相关内容,找出了leetcode相关的专题来做,碰到了买卖股票的一系列问题,故记录以备之。

一、入门一级:只能买卖一次股票,求最大利润

Title: 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:
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:
Input: [7, 6, 4, 3, 1]
Output: 0

In this case, no transaction is done, i.e. max profit = 0.

思路:本题的解法是记录下最小值并与之后遇到的值与该最小值做差并保留最大值。

class Solution {
public:
    int maxProfit(vector<int>& prices) {

        int n = prices.size(), buy = INT_MIN, sell = 0;
        if(n==0) return 0;

        for(int i=0; i<n; i++)
        {
            buy =  max(buy, -prices[i]);
            sell = max(sell, prices[i] + buy);
        }
        return sell;
    }
};

二、入门二级:可以多次买入卖出,求最大利润

Title: 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) {

        int buy = INT_MIN, sell = 0, n = prices.size();
        if(n==0) return 0;

        for(int i=0; i<n; i++)
        {
            buy = max(buy, sell-prices[i]);
            sell = max(sell, buy + prices[i]);
        }
       return sell;
    }
};

三、进阶级:最多可进行两次买卖操作

Title: 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).

思路:本题相当于前两题的合并,分别保存两次交易的买入卖出后的利润,写程序时应该清楚何种方法可仅进行一次买入卖出操作,何种方法为可进行多次买入卖出操作。

class Solution {
public:
    int maxProfit(vector<int>& prices) {

        int n = prices.size();
        if(n==0) return 0;
        int sell1 = 0, sell2 = 0, buy1 = INT_MIN, buy2 = INT_MIN;

        for(int i =0; i<n; i++)
        {
            buy1 = max(buy1, -prices[i]);
            sell1 = max(sell1, prices[i]+buy1);
            buy2 = max(buy2, sell1-prices[i]);
            sell2 = max(sell2, prices[i]+buy2);
        }        
        return sell2;        
       }
};

四、变态级:最多进行k次交易

Title: Best Time to Buy and Sell Stock IV
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 k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

思路:
分成 k > n/2 及 k <= n/2 两部分考虑:
1. k > n/2 时,可归为上述样例二中的情况(即可进行无限次交易);
2. k <= n/2 时, 将每次的买入、卖出利润保存在数组中(与动态规划相结合)。

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {

        int n = prices.size();

        if(k>n/2)
        {
            int buy = INT_MIN, sell = 0;
            for(int i=0; i<n; i++)
            {
                buy = max(buy, sell-prices[i]);
                sell = max(sell, buy+prices[i]);
            }
            return sell;
        }

        vector<int> sell(k+1, 0);
        vector<int> buy(k+1, 0);

        for(int i=0; i<=k; i++) buy[i] = INT_MIN;

        for(int i=0; i<n; i++)
        {
            for(int j=1; j<k+1; j++)
            {

                buy[j] = max(buy[j], sell[j-1]-prices[i]);
                sell[j] = max(sell[j], buy[j]+prices[i]);

            }
        }
        return sell[k];        
    }
};

五、改进级:可进行多次交易,但每次交易后需要“冷静”一天

Title: Best Time to Buy and Sell Stock with Cooldown

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) with the following restrictions:

You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:

prices = [1, 2, 3, 0, 2]
maxProfit = 3
transactions = [buy, sell, cooldown, buy, sell]

思路: 将前一天的卖出值保存,用于之后交易时条件判定。

class Solution {
public:
    int maxProfit(vector<int>& prices) {

        int n = prices.size(), buy = INT_MIN, sell = 0, sell_pre = 0;
        for(int i=0; i<n; i++)
        {
            int old_sell = sell;
            buy = max(buy, sell_pre - prices[i]);
            sell = max(old_sell, buy + prices[i]);
            sell_pre = old_sell;
        }
        return sell;
    }
};

六、另一版改进级:每次交易需支付手续费,买卖次数无限制

Title:Best Time to Buy and Sell Stock with Transaction Fee

our are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.

Example 1:
Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {

        int n = prices.size(), buy = INT_MIN, sell = 0;
        for(int i=0; i<n; i++)
        {
            buy = max(buy, sell-fee-prices[i]);
            sell = max(sell, buy+prices[i]);
        }
        return sell;
    }
};

综上所述, 买卖股票最关键的是要将问题分为两种状态:当前手中持有股票时最大利润为多少,及将手中股票卖出后最大利润为多少。根据要求计算每一状态下的最佳值(确定状态的转换方程很重要!),最后返回手中股票卖出后的最大利润即为所求的最终结果。

展开阅读全文

没有更多推荐了,返回首页