qingcheng奕  

http://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/

这三道题,很好的进阶。1题简单处理,2题使用贪心,3题使用动态规划。

话说这叫一维动态规划,嗯。又复习了《算法导论》中和贪心以及动态规划有关的知识,记录如下:

动态规划的标志:最优子结构、子问题重叠。

      1.找最优子结构

      2.定义递归公示(列一个式子出来,并定义好这个式子到底是什么意思)。

      3.写自底向上或递归备忘录法。

 

比如本问题:f(i,j) = max{f(i,k)+f(k,j)}           其中:f(i,j)表示从i到j的所有数,进行一次交易能获得的最多的钱数。最终要求的是f(0,n-1),k从1到n-2.

再深化一下:

      fp(i,j)表示从i 到 j 进行最多进行 p 次交易可以获得的钱数,则:

      fp(i,j) = max {fp-1(i,j), fp-p'(i,k)+fp'(k,j)}     其中:p'从1到p-1,k从i+1到j-1.

这大概叫二维动态规划(或许)。

 

贪心算法是从局部最优,能够做到全局最优。可分成一步步的,当前的选择受之前做过的选择的影响。而动态规划,是受后面要做的选择的影响。

 

于是有了下面代码,复杂度O(n2)然后超时了。

class Solution {
public:
    //start 第一个元素,end 最后一个元素的下标
    int onceBuyAndSell(vector<int> &prices,int start,int end)
    {
        int ans = 0;
        int max = prices[end];
        for(int i = end - 1;i>=start;i--)
        {
            if(max - prices[i]>ans)
                ans = max - prices[i];
            if(prices[i]>max)
                max = prices[i];
        }
        return ans;  
    }

    int maxProfit(vector<int> &prices) {
        if(prices.empty())
            return NULL;
        if(prices.size()==1)
            return 0;

        int ans = onceBuyAndSell(prices,0,prices.size()-1);

        if(prices.size()<4 || ans == 0)
            return ans;

        int temp = 0;
        for(int itor = 2;itor<prices.size()-2;itor++)
        {
            temp = onceBuyAndSell(prices,0,itor) + onceBuyAndSell(prices,itor+1,prices.size()-1);
            if(temp> ans)
                ans = temp;
        }
        return ans;
    }
};

在网上找资料,参考了http://blog.unieagle.net/2012/12/05/leetcode%E9%A2%98%E7%9B%AE%EF%BC%9Abest-time-to-buy-and-sell-stock-iii%EF%BC%8C%E4%B8%80%E7%BB%B4%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/

使用了动态规划中打表的方法,降低了复杂度O(n).代码如下:

class Solution {
public:
        vector<int> ansN;
    
//ansN[i]表示,从i到最后的所有元素,只进行一次交易的话,可以得到的最多值。
void onceBuyAndSell(vector<int> &prices,int start,int end) { int ans = 0; int max = prices[end]; ansN[end] = 0; for(int i = end - 1;i>=start;i--) { if(max - prices[i]>ans) ans = max - prices[i]; if(prices[i]>max) max = prices[i]; ansN[i] = ans; } } int maxProfit(vector<int> &prices) { if(prices.empty()) return NULL; if(prices.size()==1) return 0; ansN.resize(prices.size()); //先来一遍从后面计算的。 onceBuyAndSell(prices,0,prices.size()-1); if(prices.size()<4 ) return ansN[0]; int min = prices[0]; int ans2 = 0; int ans = ansN[0]; for(int itor = 1;itor<prices.size()-2;itor++) { if(prices[itor] - min>ans2) ans2 = prices[itor] - min; if(prices[itor]<min) min = prices[itor]; if(ans2 + ansN[itor+1]> ans) ans = ans2 + ansN[itor+1]; } return ans; } };

 

posted on 2014-01-02 19:00  qingcheng奕  阅读(171)  评论(0编辑  收藏  举报