博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Leetcode:Maximal Rectangle
阅读量:4964 次
发布时间:2019-06-12

本文共 3458 字,大约阅读时间需要 11 分钟。

  题目大意:给一个由0和1组成r行c列的矩阵M,找出其中面积最大的由1组成的矩形。  

  这道题目和之前一道提供高度计算最大矩形的题目是一样的,这里也一块说一下。这道题目提供若干宽度为1的柱形,求其中最大的矩形面积,柱形由高度和位置唯一决定,由一个数组H表示,H[i]表示编号为i的柱形的高度。

  显然如果一个矩形最大,那么其必定包含一个高度最低的柱形,设其下标为i。假设矩形的左右边界矩形的下标为a+1和b-1,那么必然有H[a]<H[i]和H[b]<H[i],否则矩形可以进一步扩大,与其最大这一前提相悖。对于每一个柱形H[i],利用左右边界的性质可以决定唯一的最大矩形候选,而只要挑选出所有矩形候选中面积最大者,就是我们需要的结果。下面稍微说明一下如何在O(n)时间内找到每一个最大矩形候选的右边界。从0到n遍历整个H,将所有未找到右边界的柱形加入到一个栈结构中。显然栈中的柱形高度应该是递增的。每次遇到一个新的柱形,将栈中所有高度比其小的柱形全部弹出并设置右边界为新柱形,最后将新柱形加入到栈中。等到遍历结束,就将所有栈中剩余的柱形的右边界设置为n(因为剩余的都是没有匹配到右边界的)。同理可以利用类似的思路得到所有矩形候选的左边界。这两个过程的时间复杂度都是O(n)(因为每一个柱形只入栈和出栈各一次,共n个柱形)。有了左右边界计算面积就很容易了,可以在O(n)的时间复杂度内完成。

  因此对于上面的这种问题我们始终能在O(n)的时间复杂度内解决。

  现在说明如何解决Maximal Rectangle这道题目。首先我们可以将矩阵的第0行到第i行理解为一个柱形图,且第j列的高度为M[i][j],M[i-1][j],...,M[0][j]中只包含1的最长前缀的长度。可以通过动态规划得到第i行第j列的高度H[i][j],因为H[i][j] = 1 == M[i][j] ? H[i-1][j] + 1 : 0。这样我们要找面积最大的只由1组成的矩形等价于找r个柱形图中最大的矩形,每个柱形图通过的方法可以在O(c)时间内计算得到,故总时间为O(rc),加上动态规划所花费的O(rc)的时间,因此总的时间复杂度为O(rc)。

  下面上代码:

1 class Solution { 2     public int maximalRectangle(char[][] matrix)  3     { 4         if(matrix.length == 0 || matrix[0].length == 0) 5         { 6             return 0; 7         } 8         int h = matrix.length; 9         int w = matrix[0].length;10         int[] heights = new int[w];11         int max = 0;12         for(int i = 0; i < h; i++)13         {14             char[] row = matrix[i];15             for(int j = 0; j < w; j++)16             {17                 heights[j] = row[j] == '0' ? 0 : heights[j] + 1;18             }19             max = Math.max(max, theLargestArea(heights));20         }21         return max;22     }23     24     public int theLargestArea(int[] heights)25     {        26         int n = heights.length;27         int[] leftLower = new int[n];28         int[] rightLower = new int[n];29         30         IntStack stk = new IntStack(n + 1);31         for(int i = 0; i < n; i++)32         {33             int h = heights[i];34             while(stk.size() > 0 && heights[stk.peek()] > h)35             {36                 rightLower[stk.pop()] = i;37             }38             stk.push(i);39         }40         while(stk.size() > 0)41         {42             rightLower[stk.pop()] = n;43         }44 45         for(int i = n - 1; i >= 0; i--)46         {47             int h = heights[i];48             while(stk.size() > 0 && heights[stk.peek()] > h)49             {50                 leftLower[stk.pop()] = i;51             }52             stk.push(i);53         }54         while(stk.size() > 0)55         {56             leftLower[stk.pop()] = -1;57         }58         59         int max = 0;60         for(int i = 0; i < n; i++)61         {62             int area = (rightLower[i] - leftLower[i] - 1) * heights[i];63             max = Math.max(max, area);64         }65         66        // System.out.println(Arrays.toString(heights) + " : " + max);67         return max;68     }69     70     private static class IntStack{71         int[] arr;72         int top = 0;73         public IntStack(int capacity)74         {75             arr = new int[capacity];76         }77         public void push(int val)78         {79             arr[top++] = val;80         }81         public int pop()82         {83             return arr[--top];84         }85         public int peek()86         {87             return arr[top - 1];88         }89         public int size(){90             return top;91         }92     }93 }
View Code

 

  

 

转载于:https://www.cnblogs.com/dalt/p/7774859.html

你可能感兴趣的文章
CSS3阴影 box-shadow的使用和技巧总结
查看>>
DataMining--Python基础入门
查看>>
单片机复位电路
查看>>
php json_decode失败,返回null
查看>>
获取单选按钮选中的值
查看>>
oracle 分页
查看>>
助教学期总结
查看>>
绘制基本 图形之矩形与多边形
查看>>
3-day3-list-truple-map.py
查看>>
02: djangorestframework使用
查看>>
7zip 自解压安装程序
查看>>
Graph-tool简介 - wiki
查看>>
jenkins 离线安装插件 ,插件的下载地址
查看>>
Edit控件显示多行文字
查看>>
java 日期与时间类
查看>>
JS第二周
查看>>
杭电1217————不像最短路的"最短路"
查看>>
【iCore3双核心板】发布 iCore3 硬件手册!
查看>>
Leetcode Word Break
查看>>
css性质
查看>>