棧和隊列——求最大子矩陣的大小

【題目】
  給定一個整型矩陣map,其中的值只有0和1兩種,求其中全是1的所有矩形區域中,最大的矩形區域爲1的數量。
  例如:
  1 1 1 0
  其中,最大的矩形區域有3個1,所以返回3
  再如:
  1 0 1 1
  1 1 1 1
  1 1 1 0
  其中,最大的矩形區域有6個1,所以返回6

【解答】
  1、矩陣的行數爲N,以每一行做切割,統計以當前行作爲底的情況下,每個位置往上爲1的數量。使用高度數組height來表示
  例如
  1 0 1 1
  1 1 1 1
  1 1 1 0
  以第1行做切割後,height={1,0,1,1},height[j]表示目前的底上(第1行),j位置往上(包括j位置)有多少個連續的1。
  以第2行做切割後height={2,1,2,2},注意到從第一行到第二行,height數組的更新是十分方便的,即height[j] = map[i][j]+1。
  以第3行做切割後,height={3,2,3,0}
  
  2、對於每一次切割 ,都利用更新後的height數組來求出以每一行爲第的情況下,最大的矩形是什麼。那麼這麼多次切割後,最大的矩形就是我們要的。講一下怎麼求最大的矩形,利用棧,比如,height是[3,2,3,0],就讓他們依次入棧,要求從棧頂到棧底要始終滿足從大到小,如果將要入棧的大於棧頂元素,則直接將其壓入,如果將要入棧的小於棧頂元素,那就將棧頂元素依次彈出,直到滿足入棧的元素大於棧頂元素才讓其入棧,那麼,注意下面這句話,當出現要入棧的元素小於棧頂元素的時候,將要入棧的元素的位置記爲i,棧頂元素爲j,棧頂元素下面的元素爲k,那麼,當前形成的最大的矩形就是(i-k-1)*height[j],即使在中間的時候有時候會計算錯誤(具體錯誤自己琢磨吧),在最後也會被糾正過來
  
  整個過程就是如下代碼中的maxRecSize方法。步驟2的實現是如下代碼中的maxRecFromBottom方法,具體的細節自己走代碼吧

import java.util.*;
class test{
    public static void main(String[] args){
        //定義map矩陣
        int[][] map = {{1,0,1,1},{1,1,1,1},{1,1,1,0}};
        //調用函數
        int max = maxRecSize(map);
        //輸出
        System.out.println(max);

    }

    public static int maxRecSize(int[][] map){
        //如果是空的,返回
        if(map==null || map.length==0 || map[0].length==0){
            return 0;
        }
        //用來存放最大值,最後返回
        int maxArea = 0;
        //高度數組
        int[] height = new int[map[0].length];
        //計算高度數組
        for(int i=0;i<map.length;i++){
            for(int j=0;j<map[0].length;j++){
                height[j] = map[i][j]==0?0:height[j]+1;
            }
            //在每一層都計算一遍最大子矩陣,找到最大的
            maxArea = Math.max(maxRecFromBottom(height),maxArea);
        }
        return maxArea;
    }

    public static int maxRecFromBottom(int[] height){
        //如果高度數組爲空,返回
        if(height==null || height.length==0){
            return 0;
        }
        int maxArea = 0;
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0;i<height.length;i++){
            while(!stack.isEmpty() && height[i]<=height[stack.peek()]){
                int j = stack.pop();
                int k = stack.isEmpty()?-1:stack.peek();
                int curArea = (i-k-1)*height[j];
                maxArea = Math.max(maxArea,curArea);
            }
            stack.push(i);
        }
        while(!stack.isEmpty()){
            int j = stack.pop();
            int k = stack.isEmpty()?-1:stack.peek();
            int curArea = (height.length-k-1)*height[j];
            maxArea = Math.max(maxArea,curArea);
        }
        return maxArea;
    }
}
發佈了89 篇原創文章 · 獲贊 211 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章