Leetcode——Best Time to Buy and Sell Stock系列

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 (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

法:(动态规划)记录当前最低价,循环遍历,以最低价买,当前价卖,选择最大值。换言之,设dp[i]表示第i天卖出能获得的最大利润,buyPrice为0到i-1天的最小值,则max(dp)即为所求。由于dp[i]只与buyPrice相关,则可使用变量dp逐步迭代,将空间复杂度降为O(1)  。该算法的时间复杂度是O(n) 。

    int maxProfit(vector<int>& prices) {
        if(prices.size() < 2)
            return 0;
        int dp = 0;
        int buyprice = prices[0];
        for(int i = 1; i < prices.size(); i++)
        {
            buyprice = min(buyprice, prices[i - 1]);
            dp = max(dp, prices[i] - buyprice);
        }
        return dp;
    }

122. 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 (i.e., buy one and sell one share of the stock multiple times).

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

法:只要后一天比前一天高即购买,时间复杂度是O(n),空间复杂度为O(1)

    int maxProfit(vector<int>& prices) {
       int res = 0;
        for(int i = 1; i < prices.size(); i ++)
            if(prices[i] - prices[i-1] > 0)
                res += prices[i] - prices[i-1];
        return res;
    }

 

123. 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 (i.e., you must sell the stock before you buy again).

法:(动态规划)以第i天为分界线,计算第i天之前(包含第i天)至多进行一次交易的最大收益preProfit[i],和第i天之后(包含第i天)至多进行一次交易的最大收益postProfit[i]。最后再遍历一遍,max{preProfit[i] + postProfit[i]} (0≤i≤n-1)就是最大收益。在第i天既进行买交易又进行卖交易,故preProfit[i]与postProfit[i]在计算时均包含第i天。其中,

preProfit[i] = max(preProfit[i - 1], prices[i] - curmin)   // 买入的日子导致curmin变动,卖出的日子为prices[i]

postProfit[i] = max(preProfit[i + 1], curmax - prices[i + 1])    // 卖出的日子导致curmax变动, 买入的日子为prices[i + 1]

时间复杂度是O(n),空间复杂度为O(n)

    int maxProfit(vector<int>& prices) {
        if(prices.size() < 2)
            return 0;
        int res = 0;
        vector<int> dpre(prices.size());
        vector<int> dpost(prices.size());
        int minprice = prices[0];
        for(int i = 1; i < prices.size(); i ++)
        {
            minprice = min(minprice, prices[i - 1]);
            dpre[i] = max(dpre[i - 1], prices[i] - minprice);
        }
        int maxprice = prices[prices.size() - 1];
        for(int i = prices.size() - 2; i >= 0; i --)
        {
            maxprice = max(maxprice, prices[i + 1]);
            dpost[i] = max(dpost[i + 1], maxprice - prices[i + 1]);
        }
        for(int i = 0; i < prices.size(); i ++)
            res = max(res, dpre[i] + dpost[i]);
        return res;
    }

 

188. Best Time to Buy and Sell Stock IV(k次)

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.

法:设dp[j]表示在第i天之前(含第i天)完成j次交易时的最大收益(交易指一次买进或者一次卖出),则转移方程如下:dp[j] = max(dp[j], dp[j - 1] + prices[i] * [1, -1][j % 2])。当j为奇数时,交易类型为买进(因为第1笔交易只能是买进);当j为偶数时,交易类型为卖出。当k>n/2时,即转化为交易次数不再受限制,即此题就转化为Best Time to Buy and Sell Stock II的计算。

        空间复杂度降为O(k)  ,时间复杂度是O(n*k) 。

    int maxProfitInfinite(vector<int>& prices) {
       int res = 0;
        for(int i = 1; i < prices.size(); i ++)
            if(prices[i] - prices[i-1] > 0)
                res += prices[i] - prices[i-1];
        return res;
    }
    int maxProfit(int k, vector<int>& prices) {
        if(k >= prices.size() / 2)
            return maxProfitInfinite(prices);         
        vector<int> dp(2*k + 1, INT_MIN);
        dp[0] = 0;
        for(int i = 0 ; i < prices.size(); i ++)
            for(int j = 1; j <= min(2 * k , i + 1); j ++)
            {
                if(j % 2)
                    dp[j] = max(dp[j], dp[j-1] - prices[i]);
                else
                    dp[j] = max(dp[j], dp[j-1] + prices[i]);
            }
        return dp[2*k];
     }

714. Best Time to Buy and Sell Stock with Transaction Fee

Your 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.

法:(动态规划)对于第i天的最大收益,应分成两种情况,一是该天结束后手里没有stock,可能是保持前一天的状态也可能是今天卖出了,此时令收益为cash;二是该天结束后手中有一个stock,可能是保持前一天的状态,也可能是今天买入了,用hold表示。由于第i天的情况只和i-1天有关,所以用两个变量cash和hold就可以,不需要用数组。

    int maxProfit(vector<int>& prices, int fee) {
        int cash = 0, hold = - prices[0];
        for(int i = 1; i < prices.size(); i ++)
        {
            cash = max(cash, hold + prices[i] - fee);
            hold = max(hold, cash - prices[i]);
        }
        return cash;
    }

 

309. 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)

法:(动态规划)

1.在第i天买一支股票还能剩下的利润=第(i-2)天销售能够剩余的利润-第i天股票的价钱.

2.在第i天卖一支股票总的利润=第(i-1)天买股票剩下的最大利润+当前股票的价格.

需要维护两个状态的信息,一个是买股票所得到的剩余最大利润,一个是卖出股票之后得到的最大利润,他们互相依赖.

对于买来说,当天是否买取决于买了之后是否比之前买所剩余的利润大,即状态转移方程为:

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

对于卖来说,同样当天是否将这只股票卖掉取决于卖掉能否获得更大的利润,状态转移方程为:

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

    int maxProfit(vector<int>& prices) {
        if(prices.size() < 2)
            return 0;
        vector<int> buy(prices.size() + 1, 0), sell(prices.size() + 1, 0);
        buy[1] = - prices[0];
        for(int i = 2; i <= prices.size(); i++)
        {
            buy[i] = max(buy[i-1], sell[i-2] - prices[i-1]);
            sell[i] = max(sell[i-1], buy[i-1] + prices[i-1]);
        }
        return sell[prices.size()];
    }

猜你喜欢

转载自blog.csdn.net/qy724728631/article/details/81977941