zoukankan      html  css  js  c++  java
  • [LeetCode]Maximal Rectangle

    题目:Maximal Rectangle

    找到最大的全1矩阵。

    1 0 1 0 0
    1 0 1 1 1
    1 1 1 1 1
    1 0 0 1 0

     思路:

    要求上面的解,先看下面的问题:

    一个数组A[]={5,6,7,8,3};对应如下的直方图,求他的最大矩形的面积。

    普通的思路,就是循环遍历,i=0~a.length-1;

    然后里面从j=i~a.length-1,在最里层循环中,找到i到j的最小高度,求出它的矩阵面积,然后和最大值比较。

    如此就能找到最大面积。

        private int largestRectangleArea(int[] height){
            int[] min = new int[height.length];//记录i~j的最小高度
            int max = 0;
            for (int i = 0; i < height.length; i++) {
                //最好的情况都无法超过最大面积,则跳过
                if(height[i] > 0 && max/height[i] >= height.length - i)continue;
                for(int j = i;j < height.length;j++){
                    //找到i到j的最小高度
                    if(i == j)min[j] = height[j];
                    else if(height[j] < min[j - 1])min[j] = height[j];
                    else min[j] = min[j - 1];
                    //i到j的矩阵面积
                    int curArea = min[j]*(j - i + 1);
                    if(curArea > max) max = curArea;
                }
            }
            return max;
        }

    用栈可以优化它的搜索速度。

    1) 遍历高度数组,当数组的值是递增(即当前的高度大于栈顶的元素对应的高度)的状态或栈为空,就将当前高度下标入栈,下标加1。

    2) 当数组元素不是递增时,即当前的高度小于栈顶元素对应的高度时,弹出该元素,求当前数组元素的前一个元素与当前栈顶元素的矩形面积Height[stack.peek()]*(i - stack.peek() - 1)。

    3) 比较该面积和最大面积。

    直到1) 再次满足,则入栈。

    private int largestRectangleArea2(int[] height){
            Stack<Integer> stack = new Stack<Integer>();
            int newHeight[] = new int[height.length + 1];
            newHeight = Arrays.copyOf(height, height.length + 1);
            int i = 0,max = 0,num;
            while(i < newHeight.length){
                if(stack.isEmpty() || newHeight[stack.peek()] <= newHeight[i])//栈空或非递增则入栈
                    stack.push(i++);
                else{//出栈
                    int index = stack.pop();
                    num = stack.isEmpty() ? i : i - stack.peek() - 1;
                    max = Math.max(max, newHeight[index]*num);//求面积并取最大
                }
            }
            return max;
        }

    有了上面的算法,就可以了求解Maximal Rectangle的问题了。

    每一行遍历二维数组,按照下面的规则刷新数组的值:Arr[i][j]=Arr[i-1][j]+Arr[i][j] (Arr[i][j] > 0);

    这样就可以得到每一行的直方图,再调用上面的方法求得最大面积。

    package com.example.medium;
    
    import java.util.Arrays;
    import java.util.Stack;
    
    /**
     * 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.
     * @author FuPing
     *
     */
    public class MaximalRectangle {
        private int largestRectangleArea(int[] height){
            int[] min = new int[height.length];//记录i~j的最小高度
            int max = 0;
            for (int i = 0; i < height.length; i++) {
                //最好的情况都无法超过最大面积,则跳过
                if(height[i] > 0 && max/height[i] >= height.length - i)continue;
                for(int j = i;j < height.length;j++){
                    //找到i到j的最小高度
                    if(i == j)min[j] = height[j];
                    else if(height[j] < min[j - 1])min[j] = height[j];
                    else min[j] = min[j - 1];
                    //i到j的矩阵面积
                    int curArea = min[j]*(j - i + 1);
                    if(curArea > max) max = curArea;
                }
            }
            return max;
        }
        private int largestRectangleArea2(int[] height){
            Stack<Integer> stack = new Stack<Integer>();
            int newHeight[] = new int[height.length + 1];
            newHeight = Arrays.copyOf(height, height.length + 1);
            int i = 0,max = 0,num;
            while(i < newHeight.length){
                if(stack.isEmpty() || newHeight[stack.peek()] <= newHeight[i])//栈空或递增则入栈
                    stack.push(i++);
                else{//出栈
                    int index = stack.pop();
                    num = stack.isEmpty() ? i : i - stack.peek() - 1;
                    max = Math.max(max, newHeight[index]*num);//求面积并取最大
                }
            }
            return max;
        }
        public int maximalRectangle(char[][] matrix) {
            if(matrix == null || matrix.length == 0)return 0;
            int[][] intMatrix = new int[matrix.length][matrix[0].length];
            for (int i = 0; i < intMatrix.length; i++) {//转换成int的二维数组
                    for (int j = 0; j < intMatrix[0].length; j++) {
                        intMatrix[i][j] = matrix[i][j] - 48;
                    }
                }
            for(int j = 0;j < intMatrix[0].length;j++){//将每行转换成直方图
                for (int i = 1; i < intMatrix.length; i++) {
                    if(intMatrix[i][j] != 0)//当前元素非零时,统计当前元素上面不为1的高度
                        intMatrix[i][j] += intMatrix[i - 1][j];
                    }
            }
            int max = 0,lineMax = 0;
            for (int i = 0; i < intMatrix.length; i++){
                lineMax = largestRectangleArea2(intMatrix[i]);//求每一行的最大面积
                if(lineMax > max)max = lineMax;
            }
          return max;
        }
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            /*char[][] matrix = new char[][]{{'1','1','1','1','1','1','1','0'},
                    {'1','1','1','1','1','1','1','0'},
                    {'1','1','1','1','1','1','1','0'},
                    {'1','1','1','1','1','0','0','0'},
                    {'0','1','1','1','1','0','0','0'}};*/
            char[][] matrix = new char[][]{{'1','0','1','0','0'},
            {'1','0','1','1','1'},
            {'1','1','1','1','1'},
            {'1','0','0','1','0'}};
            for(char[] a : matrix){
                for(char ch :a)
                    System.out.print(ch);
                System.out.println();
            }
            MaximalRectangle rectangle = new MaximalRectangle();
            int area = rectangle.maximalRectangle(matrix);
            System.out.println(area);
    
        }
    
    }

     题目:Maximal Square

    找到最大的全1方阵。

    思路:

    首先按照上面的方法的到每一行的高度直方图,然后求行最大方阵,最后比较每个行最大方阵,得到最大的方阵。

    int LeetCode::maximalSquare(vector<vector<char>>& matrix){
        if(!matrix.size() || !matrix.at(0).size())return 0;//边为0
        vector<int>height(matrix.at(0).size() + 1, 0);//比matrix宽1,这样可以保证最后的一个数为0使得栈最后一定能清空
        int maxArea = 0;
        for (size_t i = 0; i < matrix.size(); i++){
            for (size_t j = 0; j < matrix.at(i).size(); j++){
                if (matrix.at(i).at(j) == '1'){//在上一行的height基础上加一
                    height.at(j) += 1;
                }
                else{//从零开始
                    height.at(j) = 0;
                }
            }
            //一行的高度计算完,下面求一行的最大面积
            int j = 0, width = 0;
            stack<int>s;
            while (j < height.size()){
                if (s.empty() || height.at(s.top()) <= height.at(j)){//栈空或递增时入栈
                    s.push(j);
                    ++j;
                }
                else{
                    int pos = s.top();
                    s.pop();
                    width = s.empty() ? j : j - s.top() - 1;//用当前坐标j去减,数组下标从零开始,所以要再加一
                    width = min(width, height.at(pos));//宽高中选择较小的作为正方形的边
                    maxArea = max(width*width, maxArea);//求正方形的面积
                }
            }
        }
        return maxArea;
    }
  • 相关阅读:
    jtopo
    转载model2
    转载model
    Vue -- 后台系统布局导航栏
    Vue -- iview表格 axiso调用接口数据
    Vue -- 视频&&下载 组件
    Vue -- echarts 折线图demo
    Vue -- axios封装
    Vue -- 验证码
    01 & 02 & 03笔记
  • 原文地址:https://www.cnblogs.com/yeqluofwupheng/p/6685553.html
Copyright © 2011-2022 走看看