数据结构与算法——求最大子矩阵问题

来源:互联网 发布:win10 安装ubuntu 分区 编辑:程序博客网 时间:2024/05/16 13:02

原题:给定一个整形矩阵map。其中的值只有0和1两种,求其中全是1的所有矩形区域中,最大的矩形区域为1的数量。

变形题1:

有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。

给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。

      本题应用经典的栈模型来解决。首先本题的解题思路为,建立一个直方图,从每一个直方图的两边找到比他小的位置,两个坐标的差值就是当前的最大面积。这种模型恰恰与栈的数据结构对应。首先建立一个栈,遍历每一个矩形的长度,如果比前一个值大,那么就把当前矩形值的索引值压入栈中,如果小于等于前一个值,开始结算,当前值记为a,

栈中的值为b,b的下一个位置为c,那么a-c 就是b矩形的最大面积。通过代码再来深入理解。

public class ZuidaJuzhen {/* * 思路:第一个for while循环。不断的向栈中添加坐标,如果当前坐标所代表的值大于栈顶则添加成功,小于等于添加失败。 * 这样可以保证栈顶元素记录的是遍历到当前坐标位置的值是不断增大的。这是计算之前的所有坐标到最大坐标这段距离的面积。 * 最后一个while循环的时候,肯定栈中还剩一部分元素,这是采用同样的办法,计算之前的所有坐标到最大坐标这段距离的面积, * 只不过最大坐标变成了数组长度。 * */public static int maxfrombottom(int[] height){int max=0;Stack<Integer> stack = new Stack<Integer>();for(int i=0;i<height.length;i++){while(!stack.empty()&&height[i]<=height[stack.peek()]){int j = stack.pop();// 此处当stack.empty是 k=-1; 很重要的地方。两个原因。1.当结算到栈底元素时,可以保证结算区域的正确性。2.就是当遇到两个相同的元素的时候也结算。遇到两个相同元素也结算// 这时相同元素的第一个的结算可能是不对的,举例: 3,4,5,3,4,1 这时第一个3 的结算区域不对(可以结算到4,但是第二个3也结算,只结算到3,所以少了一个),但是不对也没关系,因为当// 1结算时会结算3 这时候3时栈底元素,所以k=-1,令第一个三错过的区域,这时候补上了,不会漏。int k = stack.empty()?-1:stack.peek();int cur = (i-k-1)*height[j];max = Math.max(max, cur);}stack.push(i);}// 这个while循环用来收底,因为最后一个元素进入之后是需要计算的。 while(!stack.empty()){int j = stack.pop();int k = stack.empty()?-1:stack.peek();int cur = (height.length-k-1)*height[j];max = Math.max(max, cur);} return max;}public static void main(String[] args) {int[] height = {3,5,6,1};System.out.println(maxfrombottom(height));}}

这道题的思路可以解决一类问题。比如计算一个矩阵中,只有1和0组成,求出每一个都为1所组成的矩阵中,面积最大的一个,也能转换成这种模型来计算。

核心思路就是,栈这种数据结构用来解决 从两边找第一个比自己小的数。



0 0
原创粉丝点击