[Leetcode] 85, 64, 123

85. Maximal Rectangle

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 6.

Solution(1): 此题可以视为84. Largest Rectangle in Histogram的一个变体题,设MaxArea(x)为以第x行作为底(面积必须包含第x行)得到的最大矩形面积值,则此题就蜕化为84题的内容。因此可以对第一行到最后一行利用84的方法分别求解,求全局最大值即可得到最终答案。

84题解法见:http://blog.csdn.net/coderqich/article/details/77248695

Code(1):

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        int n;
        if(matrix.size()==0) return 0;
        else n = matrix[0].size();
        vector<int> H(n,0);
        
        int maxArea = 0;
        for(int i=0; i<matrix.size(); i++){
            for(int t=0; t<n; t++){
                H[t] = matrix[i][t]=='1'? H[t]+1 : 0;
            }
            maxArea = max(largestRectangleArea(H), maxArea);
        }
        return maxArea;
    }
private:
    int largestRectangleArea(vector<int>& heights) {
        if(heights.size()==0) return 0;
        
        stack<int> h;
        h.push(heights[0]);
        int max = 0;
        for(int i=1; i<heights.size(); i++){
            int t = 0;
            //中间被pop掉的几个,因为也是有序的,因此可以用同样的方法直接计算最大面积
            while(!h.empty() && h.top()>heights[i]){
                t++;
                if(h.top()*t>max) max = h.top()*t;
                h.pop();
            }
            while(t>=0){
                h.push(heights[i]);
                t--;
            }
        }
        int i = 0;
        while(!h.empty()){
            i++;
            if(h.top()*i>max) max = h.top()*i;
            h.pop();
        }
        return max;
    }
};


Solution(2):对于84题,最直观的解法就是对一个柱向左右两边扩展直至找到比它矮的柱停止,但是这样做可以超时,因此使用动规缩短时间,即使用动规来求左右端点。

状态转移方程为:

left(i, j) = max(left(i-1, j), cur_);
right(i, j) = min(right(i-1, j), cur_right); 
参考: http://blog.csdn.net/makuiyu/article/details/44857479

其中cur_left表示当前行连续的1的左端点,cur_right表示右端点的后一位(为了便于计算)。


解析:如果当前行全部为1,则left(i,j)和right(i,j)可以直接继承上一行的同一位置的值,即left(i,j)=left(i-1,j), right(i,y)=right(i-1,j)。但是如果在区间[left(i-1,j), right(i-1,j)) 之中当前行出现了0,则直接截断,因此左右端点都取更靠近cur的那个值。

Code(2):

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        int n;
        if(matrix.size()==0) return 0;
        else n = matrix[0].size();
        vector<int> H(n,0);
        vector<int> L(n,0); //记录最左边的index
        vector<int> R(n,n); //最右边的index
        
        int maxArea = 0;
        for(int i=0; i<matrix.size(); i++){
            for(int t=0; t<n; t++){
                H[t] = matrix[i][t]=='1'? H[t]+1 : 0;
            }
            int cur_left = 0;
            for(int t=0; t<n; t++){
                L[t] = matrix[i][t]=='1'? max(L[t], cur_left) : 0; 
                cur_left = matrix[i][t]=='1' ? cur_left : t+1;//当前行连续1值能够到达的最左index
            }
            int cur_right = n;
            for(int t=n-1; t>=0; t--){
                R[t] = matrix[i][t]=='1' ? min(R[t], cur_right) : n;
                cur_right = matrix[i][t]=='1' ? cur_right : t;
            }
            for(int t=0; t<n; t++){
                if(matrix[i][t]=='1'){
                    maxArea = max(H[t]*(R[t]-L[t]), maxArea);
                }
            }
        }
        return maxArea;
    }
};



64. Minimum Path Sum

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Solution: 动规,状态转移方程为:

pathsum(i,j) = min(pathsum(i-1,j), pathsum(i,j-1)) + grid(i,j);

Code:

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        if(grid.size()==0) return 0;
        int n = grid[0].size();
        vector<int> pathsum(n, 0);
        
        pathsum[0] = grid[0][0];
        for(int i=1; i<n; i++) pathsum[i] = pathsum[i-1] + grid[0][i];
        
        for(int i=1; i<grid.size(); i++){
            pathsum[0] = pathsum[0]+grid[i][0];
            for(int t=1; t<n; t++){
                pathsum[t] = min(pathsum[t-1], pathsum[t]) + grid[i][t]; 
            }
        }
        return pathsum[n-1];
    }
};



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

Solution: 此题的简化版本为121Best Time to Buy and Sell Stock,设f(x,y)为题121在[x,y]区间的解,则题123的解ans = max(f(begin,y) + f(y+1,end)),因此利用121的解法对序列正着求一次再反着求一次,然后求和的最大值即可。

Code:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()==0) return 0;
        vector<int> left(prices.size(), 0);
        int MIN = prices[0];
        for(int i=1; i<prices.size(); i++){
            MIN = min(MIN, prices[i]);
            left[i] = max(left[i-1], prices[i]-MIN);
        }
        vector<int> right(prices.size(), 0);
        int MAX = prices.back();
        for(int i=prices.size()-2; i>=0; i--){
            MAX = max(MAX, prices[i]);
            right[i] = max(right[i-1], MAX-prices[i]);
        }
        int maxAns = right[0];
        for(int i=0; i<left.size()-1; i++){
            maxAns = max(maxAns, left[i]+right[i+1]);
        }
        return maxAns;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值