8.14 dp maximalRec & bestTimeToBuy & InterleavingStr

- to do

- before 13.4] Maximal Square

mark: improve using rotating array

    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return 0;
        int m = matrix.size(), n = matrix[0].size(); 
        // dp : maxSide[i][j] stores maximalSquare's side length who uses matrix[i][j] as rightMost corner
        vector<vector<int>> maxSide(m, vector<int>(n, 0));
        int ret = 0;
        for (int i=0; i<m; ++i) {
            maxSide[i][0] = matrix[i][0]-'0';
            ret = max(ret, maxSide[i][0]);
        }
        for (int j=0; j<n; ++j) {
            maxSide[0][j] = matrix[0][j]-'0';
            ret = max(ret, maxSide[0][j]);
        }
        for (int i=1; i<m; ++i) {
            for (int j=1; j<n; ++j) {
                if (matrix[i][j]!='0')  {
                    int m1 = maxSide[i][j-1], m2 = maxSide[i-1][j], minm = min(m1, m2);
                    maxSide[i][j] = minm + (matrix[i-minm][j-minm]-'0');
                    ret = max(ret, maxSide[i][j]);
                }
            }
        }
        return ret*ret;
    }

- again Largest Rectangle in Histogram

- 1) 改進(jìn)的暴力 O(n)?

  • 最原始的暴力是從左往右遍歷,當(dāng)前ith whole bar為左界限,向右延伸找第一個(gè)矮于自己的; 算出面積。O(n^2)
  • 或者另一種想法,最大矩形必然包含了某一個(gè)立柱的全部。所以遍歷是向左右延伸,算用了當(dāng)前立柱的最大面積。(所以當(dāng)前立柱是rect內(nèi)最低高度)
    • 所以每一步想要知道lefti of 向左延伸遇到的第一個(gè)比自己矮的立柱,以及righti同理。所以area = heights[i] * (righti-lefti-1)。 這里又有兩種辦法
      1. dp 兩遍遍歷構(gòu)建leftIndex[], rightIndex[]
      2. 用非遞減stack來(lái)找lefti/righti
        先說(shuō)stack的辦法:
  1. 考慮非遞減的array【1,4,5,5,7,9】,如果算用了當(dāng)前立柱的最大面積,很簡(jiǎn)單只需要從右往左遍歷,記住incremental的寬度n-i,乘以height[i]得到面積。(雖然在重復(fù)值情況中,【n-2】的5不會(huì)得到最大值,但是最左邊的重復(fù)值會(huì)保證捕捉最大值)
  2. 如果在1的基礎(chǔ)上加上一個(gè)違反規(guī)律更小的6 => array【1,4,5,5,7,9,6】



    ===========我是啟動(dòng)畫(huà)面(xia)感(che)的分割線==============

順序的大人的看到了小矮紅i的加入,之前的簡(jiǎn)單算法hold不住了,暫停下遍歷來(lái)觀察下:
發(fā)現(xiàn)在小矮紅線以上的那些高柱其實(shí)找到了righti就是i,換而言之小矮成了高柱們一輩子的短板限制,sad;而小矮呢,它的lefti并不關(guān)心高柱們有多高多厲害,而是向左第一個(gè)比小矮還矮的柱子2hhh。
既然互不關(guān)心一拍即合,那么高柱們就退場(chǎng)了,但別漏了當(dāng)maxArea的可能性啊,所以退場(chǎng)前算一下Area:height[self] * (i-lefti-1) where lefti = s.empty()? i : s.top().

退場(chǎng)結(jié)束。
終于又回到非遞增的規(guī)則世界~可是退場(chǎng)的高柱會(huì)影響未來(lái)的面積記錄突破嗎?小矮說(shuō) 不會(huì)的,即使高柱在,未來(lái)我右邊的每個(gè)柱子往左延伸都要經(jīng)過(guò)我這一關(guān),別忘了我是他們的短板。
那好,別忘了所有柱子都要算面積,元素都是算了面積再被pop,意思是stack最后要清空。當(dāng)然可以加一個(gè)while not empty{loop},或者巧妙的
resume遍歷

  • 所以這道題和Maximal Rect相通之處就是可以把平面看做大矩陣,條形看做1,非條形看做0,尋找最大全1矩陣。
  • reference
public:
// 暴力
    int largestRectangleArea(vector<int>& heights) {
        if (heights.empty()) return 0;
        int n = heights.size();
        vector<int> h(n+2, -1);
        // left[i] gives the index of farthest reachable bar on the LHS
        vector<int> left(n+1, -1);
        vector<int> right(n+2, -1);
        //往左找第一個(gè)比自己矮的
        for (int i=1; i<=n; ++i) {
            int k = i;
            //比自己高就繼續(xù)找
            while (h[i] <= h[k-1]) k = left[k-1];
            left[i] = k;
        }
        for (int i=n; i>0; --i) {
            int k = i;
            //比自己高就繼續(xù)找
            while (h[i] <= h[k+1]) k = right[k+1];
            right[i] = k; 
        }
        int ret = 0;
        for (int i=1; i<=n; ++i) {
            ret = max(ret, h[i]*(right[i]-left[i]+1));
        }
        return ret;
    }

- 2) using stack

    int largestRectangleArea(vector<int>& heights) {
        int ret = 0, n = heights.size();
        stack<int> s;
        // want to calculate maxarea using the whole heights[i]
        // meaning: extend farthest to left, find first bar < heights[i]; same to right
        int i=0; 
        while (i<n) {
            if (s.empty() || heights[i]>=heights[s.top()]) {
                s.push(i++);
            } else {
                // calculate area of bar w/ heights[tp] as height
                int tp = s.top();
                s.pop();
                int width = s.empty()? i : i-s.top()-1;
                ret = max(ret, width*heights[tp]);
            }
        }
        while (!s.empty()) {
            // calculate area of bar w/ heights[tp] as height
            int tp = s.top();
            s.pop();
            int width = s.empty()? i : i-s.top()-1;
            ret = max(ret, width*heights[tp]);            
        }
        return ret;
    }

13.5] Best Time to Buy and Sell Stock III

lalala
開(kāi)始忘記stockI解dp存的是當(dāng)天賣會(huì)得到的收入,而非當(dāng)前最佳收入。

    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if (n<2) return 0;
        // build dp1: dp1[i] gives maxProfit so far of period [0-i]
        int minSoFar = prices[0], maxP = 0;
        vector<int> dp1(n, -1);
        for (int i=0; i<n; ++i) {
            minSoFar = min(minSoFar, prices[i]);
            maxP = max(maxP, prices[i] - minSoFar);
            dp1[i] = maxP;
        }
        // build dp2: dp2[i] gives maxProfit so far of period [i-(n-1)]
        int maxSoFar = prices[n-1];
        maxP = 0;
        vector<int> dp2(n, -1);
        for (int i=n-1; i>=0; --i) {
            maxSoFar = max(maxSoFar, prices[i]);
            maxP = max(maxP, maxSoFar - prices[i]);
            dp2[i] =maxP;
        }     
        // dp2[n] = 0
        dp2.push_back(0);
        // build dp3: 
        int maxRet = INT_MIN;
        for (int k=0; k<n; ++k) {
            maxRet = max(maxRet, dp1[k] + dp2[k+1]);
        }
        return maxRet;
    }

- naive recursive method

    bool isInterleave(string s1, string s2, string s3) {
        if (s3.size() != s1.size() + s2.size()) return false;
        if (s2.empty()) return s1.compare(s3)==0;
        if (s1.empty()) return s2.compare(s3)==0;
        if (s1[0]!=s3[0] && s2[0]!=s3[0]) return false;

        bool ret = false;
        if (s1[0]==s3[0]) ret = ret || isInterleave( s1.substr(1, s1.size()-1), s2, s3.substr(1, s3.size()-1) );
        if (s2[0]==s3[0]) ret = ret || isInterleave( s1, s2.substr(1, s2.size()-1), s3.substr(1, s3.size()-1) );
        return ret;
    }

- better dp

Make sure understand what the memo structure holds and where the bound is. Follow the equation at all time. Bug when I wasn't clear what the boundry means and another bug see comment below.

    bool isInterleave(string s1, string s2, string s3) {
       if (s1.size()+s2.size() != s3.size()) return false;
       if (s3.empty()) return true;
       int m = s1.size(), n = s2.size(), l = s3.size();
       
       vector<vector<bool>> dp(m+1, vector<bool>(n+1, false));
       dp[m][n] = true;
       for (int i=m-1; i>=0; --i) dp[i][n] = dp[i+1][n] && s1[i]==s3[i+n];
       for (int j=n-1; j>=0; --j) dp[m][j] = dp[m][j+1] && s2[j]==s3[m+j];
       
       for (int i=m-1; i>=0; --i) {
           for (int j=n-1; j>=0; --j) {
               int k = i+j;
               if (s3[k]==s1[i] || s3[k]==s2[j]) {
                   dp[i][j] = (s3[k]==s1[i] && dp[i+1][j]) ||
                              (s3[k]==s2[j] && dp[i][j+1]);
               }
           }
       }
       return dp[0][0];
    }

- optimize using rotating array

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容