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 0Return 6.
Solution(1): 此题可以视为84. Largest Rectangle in Histogram的一个变体题,设MaxArea(x)为以第x行作为底(面积必须包含第x行)得到的最大矩形面积值,则此题就蜕化为84题的内容。因此可以对第一行到最后一行利用84的方法分别求解,求全局最大值即可得到最终答案。
84题解法见:http://blog.youkuaiyun.com/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.youkuaiyun.com/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;
}
};