• [LeetCode] Best Time to Buy and Sell Stock III


     将Best Time to Buy and Sell Stock的如下思路用到此题目

    思路1:第i天买入,能赚到的最大利润是多少呢?就是i + 1 ~ n天中最大的股价减去第i天的。

    思路2:第i天买出,能赚到的最大利润是多少呢?就是第i天的价格减去 0~ i-1天中最小的。

    和前两道题比起来的话,这道题最难了,因为限制了交易次数。
    解决问题的途径我想出来的是:既然最多只能完成两笔交易,而且交易之间没有重叠,那么就divide and conquer。
    设i从0到n-1,那么针对每一个i,看看在prices的子序列[0,...,i][i,...,n-1]上分别取得的最大利润(第一题)即可。
    这样初步一算,时间复杂度是O(n2)。


    改进:
    改进的方法就是动态规划了,那就是第一步扫描,先计算出子序列[0,...,i]中的最大利润,用一个数组保存下来,那么时间是O(n)。
    第二步是逆向扫描,计算子序列[i,...,n-1]上的最大利润,这一步同时就能结合上一步的结果计算最终的最大利润了,这一步也是O(n)。
    所以最后算法的复杂度就是O(n)的。

    /*
    解释:
    首先,因为能买2次(第一次的卖可以和第二次的买在同一时间),但第二次的买不能在第一次的卖左边。
    所以维护2个表,f1和f2,size都和prices一样大。
    意义:
    f1[i]表示 -- 截止到i下标为止,左边所做交易能够达到最大profit;[0,...,i]的利润
    f2[i]表示 -- 截止到i下标为止,右边所做交易能够达到最大profit;[i,...,n-1]的利润
    那么,对于f1 + f2,寻求最大即可。
    */

     对于f1[i],求解过程中用price[i] 减去之前的最小值 和 f1[i-1]做比较,取最大值

    动态规划转移方程 f1[i] = max(f1[i-1], price[i]- min)

    对于f2[i],求解过程中用后面的最大值减去price[i]和f2[i+1]做比较,取最大值

     动态规划转移方程 f2[i] = max(f2[i+1], max-price[i])

    思路解释完毕,上code:

    minX[i] 表示0 到 i 的最小值 的price

    max[i] 表示i到n-1的最大值的price

     1 class Solution {
     2     public:
     3         int maxProfit(vector<int> &prices) {
     4             if (prices.size() == 0)
     5                 return 0;
     6 
     7             vector<int> f1(prices.size());
     8             vector<int> f2(prices.size());
     9 
    10             vector<int> minX(prices.size());
    11             vector<int> maxX(prices.size());
    12 
    13             minX[0] = prices[0];
    14             for(int i = 1; i< prices.size();i++ )
    15             {
    16                 minX[i] = min(minX[i-1], prices[i]);
    17             }
    18 
    19             maxX[prices.size()-1] = prices[prices.size()-1];
    20             for(int i = prices.size() -2; i >=0; i-- )
    21             {
    22                 maxX[i] = max(maxX[i+1], prices[i]);
    23             }
    24 
    25             f1[0] = 0;
    26             for(int i = 1; i< prices.size();i++ )
    27             {
    28                 f1[i] = max(f1[i-1],prices[i]-minX[i]);
    29             }
    30 
    31             f2[prices.size()-1] = 0;
    32             for(int i = prices.size() -2; i >=0; i-- )
    33             {
    34                 f2[i] = max(f2[i+1],maxX[i]- prices[i]);
    35             }
    36 
    37 
    38             int sum = 0;
    39 
    40             for(int i = 1; i< prices.size();i++ )
    41                 sum = max(sum, f1[i] + f2[i]);
    42 
    43             return sum;
    44 
    45         }
    46 };

    优化:可以对上述code稍微优化一下,maxX 和minX array 并不需要,只要保留一个变量mini和maxX即可,不过由于f1和f2 的存在,空间复杂度还是O(n)

     1 class Solution {
     2     public:
     3         int maxProfit(vector<int> &prices) {
     4             if (prices.size() == 0)
     5                 return 0;
     6 
     7             vector<int> f1(prices.size());
     8             vector<int> f2(prices.size());
     9     
    10             int mini = prices[0];
    11             f1[0] = 0;
    12             for(int i = 1; i< prices.size();i++ )
    13             {   
    14                 f1[i] = max(f1[i-1],prices[i]-mini);
    15                 mini = min(mini, prices[i]);
    16             }   
    17 
    18             int maxi = prices[prices.size()-1];
    19             f2[prices.size()-1] = 0;
    20             for(int i = prices.size() -2; i >=0; i-- )
    21             {   
    22                 f2[i] = max(f2[i+1],maxi - prices[i]);
    23                 maxi = max(maxi, prices[i]);
    24             }   
    25 
    26             int sum = 0;
    27 
    28             for(int i = 1; i< prices.size();i++ )
    29                 sum = max(sum, f1[i] + f2[i]);
    30 
    31             return sum;
    32 
    33         }   
    34 };
  • 相关阅读:
    《实战Java高并发程序设计》读书笔记一
    《实战Java高并发程序设计》读书笔记二
    SprintBoot学习(三)
    SprintBoot学习(二)
    SprintBoot学习(一)
    jQuery学习(三)
    jQuery学习(二)
    jQuery学习(一)
    利用activeX控件在网页里自动登录WIN2003远程桌面并实时控制
    上传读取Excel文件数据
  • 原文地址:https://www.cnblogs.com/diegodu/p/3822539.html
Copyright © 2020-2023  润新知