首页 > 试题广场 >

最大矩形

[编程题]最大矩形
  • 热度指数:1639 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个仅包含 0 和 1 ,大小为 n*m 的二维二进制矩阵,找出仅包含 1 的最大矩形并返回面积。

数据范围: 保证输入的矩形中仅含有 0 和 1

例如输入[[1,0,1,0,0],[1,1,1,1,0],[1,1,1,1,1],[1,0,0,1,0]]时,对应的输出为8,所形成的最大矩形如下图所示:
示例1

输入

[[1]]

输出

1
示例2

输入

[[1,1],[0,1]]

输出

2

说明

第一列的两个 1 组成一个矩形    
示例3

输入

[[0,0],[0,0]]

输出

0
示例4

输入

[[1,0,1,0,0],[1,1,1,1,0],[1,1,1,1,1],[1,0,0,1,0]]

输出

8
import java.util.*;


public class Solution {
    public int getLargestArea(int[] heights) {
        LinkedList<Integer> stack = new LinkedList<>();
        int maxArea = 0;
        int i = 0;
        while (i <= heights.length) {
            int h = (i == heights.length) ? 0 : heights[i];
            if (stack.isEmpty() || h >= heights[stack.peek()]) {
                stack.push(i);
                i++;
            } else {
                int height = heights[stack.pop()];
                int width = stack.isEmpty() ? i : i - stack.peek() - 1;
                maxArea = Math.max(maxArea, height * width);
            }
        }
        return maxArea;
    }

    public int maximalRectangle (int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        }
        int m = matrix.length;
        int n = matrix[0].length;
        int maxArea = 0;
        int[] heights = new int[n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 1) {
                    heights[j]++;
                } else {
                    heights[j] = 0;
                }
            }
            maxArea = Math.max(maxArea, getLargestArea(heights));
        }
        return maxArea;
    }
}

发表于 2024-05-12 16:22:58 回复(0)
压缩矩阵
暴力求解的时间复杂度为 O(M^3*N^3)
该解法的时间复杂度为O(N^2*M)
从矩阵第一行开始到matrix[0].length行遍历矩阵
再从矩阵第二行开始到matrix[0].length行遍历矩阵
............一直到最后一行

用arr[]来存储矩阵的类加值

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param matrix int整型二维数组 
     * @return int整型
     */
    public int maximalRectangle (int[][] matrix) {
        // write code here
        int maxS=0;
        for(int i=0;i<matrix.length;i++){
            int[] arr=new int[matrix[0].length];
            for(int j=i,row=1;j<matrix.length;j++){
                int sum=0;
                for(int k=0;k<matrix[0].length;k++){
                    arr[k]+=matrix[j][k];
                    if(arr[k]==row){
                        sum+=arr[k];
                        maxS=Math.max(maxS,sum);
                    }else{
                        sum=0;
                    }
                }
                row++;
            }
        }
        return maxS;
    }
}


发表于 2022-03-08 16:16:49 回复(0)

单调栈(算法流程)

先做一个预处理,计算每个位置包括自己在内,往右有多少个连续的1。这样矩阵的每一列就都处理成了一个直方图。然后我们对矩阵的每一列都利用单调栈求一遍直方图内求最大矩形面积,从中选出最大的面积就可以了。
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param matrix int整型二维数组 
     * @return int整型
     */
    public int maximalRectangle (int[][] matrix) {
        int n = matrix.length;
        int m = matrix[0].length;
        // 计算每个位置包括自己在内,右边有多少个连续的1
        for(int i = 0; i < n; i++){
            for(int j = m - 2; j >= 0; j--){
                matrix[i][j] = matrix[i][j] == 1? matrix[i][j] + matrix[i][j + 1]: 0;
            }
        }
        int maxArea = 0;
        int j = 0;
        while(j < m){
            int maxHeight = 0;
            int[] heights = new int[n];
            for(int k = 0; k < n; k++){
                heights[k] = matrix[k][j];
                maxHeight = Math.max(maxHeight, heights[k]);
            }
            if(maxHeight == 0) {
                j++;
                continue;
            }
            // 来一遍直方图内的最大矩形
            maxArea = Math.max(maxArea, largestRectangleArea(heights));
            j++;
        }
        return maxArea;
    }
    
    private int largestRectangleArea(int[] heights) {
        Stack<Integer> stack = new Stack<>();
        int maxArea = 0, n = heights.length;
        for(int i = 0; i < n; i++){
            while(!stack.isEmpty() && heights[i] < heights[stack.peek()]){
                int h = heights[stack.pop()];
                int L = stack.isEmpty()? 0: stack.peek() + 1;
                maxArea = Math.max(maxArea, h*(i - L));
            }
            stack.push(i);
        }
        while(!stack.isEmpty()){
            int h = heights[stack.pop()];
            int L = stack.isEmpty()? 0: stack.peek() + 1;
            maxArea = Math.max(maxArea, h*(n - L));
        }
        return maxArea;
    }
}

复杂度分析

预处理的时间复杂度为O(n*m),随后每一列都走“直方图内求最大矩形(单调栈时间复杂度O(n))”的算法流程,一共m列,因此整体的时间复杂度仍然为O(n*m)。
发表于 2021-12-23 13:10:22 回复(0)