Find largest rectangle containing only zeros in an N×N binary matrix

前端 未结 8 2407
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 06:25

Given an NxN binary matrix (containing only 0\'s or 1\'s), how can we go about finding largest rectangle containing all 0\'s?

Example:

      I
    0          


        
8条回答
  •  猫巷女王i
    2020-11-22 06:45

    Here is J.F. Sebastians method translated into C#:

    private Vector2 MaxRectSize(int[] histogram) {
            Vector2 maxSize = Vector2.zero;
            int maxArea = 0;
            Stack stack = new Stack();
    
            int x = 0;
            for (x = 0; x < histogram.Length; x++) {
                int start = x;
                int height = histogram[x];
                while (true) {
                    if (stack.Count == 0 || height > stack.Peek().y) {
                        stack.Push(new Vector2(start, height));
    
                    } else if(height < stack.Peek().y) {
                        int tempArea = (int)(stack.Peek().y * (x - stack.Peek().x));
                        if(tempArea > maxArea) {
                            maxSize = new Vector2(stack.Peek().y, (x - stack.Peek().x));
                            maxArea = tempArea;
                        }
    
                        Vector2 popped = stack.Pop();
                        start = (int)popped.x;
                        continue;
                    }
    
                    break;
                }
            }
    
            foreach (Vector2 data in stack) {
                int tempArea = (int)(data.y * (x - data.x));
                if(tempArea > maxArea) {
                    maxSize = new Vector2(data.y, (x - data.x));
                    maxArea = tempArea;
                }
            }
    
            return maxSize;
        }
    
        public Vector2 GetMaximumFreeSpace() {
            // STEP 1:
            // build a seed histogram using the first row of grid points
            // example: [true, true, false, true] = [1,1,0,1]
            int[] hist = new int[gridSizeY];
            for (int y = 0; y < gridSizeY; y++) {
                if(!invalidPoints[0, y]) {
                    hist[y] = 1;
                }
            }
    
            // STEP 2:
            // get a starting max area from the seed histogram we created above.
            // using the example from above, this value would be [1, 1], as the only valid area is a single point.
            // another example for [0,0,0,1,0,0] would be [1, 3], because the largest area of contiguous free space is 3.
            // Note that at this step, the heigh fo the found rectangle will always be 1 because we are operating on
            // a single row of data.
            Vector2 maxSize = MaxRectSize(hist);
            int maxArea = (int)(maxSize.x * maxSize.y);
    
            // STEP 3:
            // build histograms for each additional row, re-testing for new possible max rectangluar areas
            for (int x = 1; x < gridSizeX; x++) {
                // build a new histogram for this row. the values of this row are
                // 0 if the current grid point is occupied; otherwise, it is 1 + the value
                // of the previously found historgram value for the previous position. 
                // What this does is effectly keep track of the height of continous avilable spaces.
                // EXAMPLE:
                //      Given the following grid data (where 1 means occupied, and 0 means free; for clairty):
                //          INPUT:        OUTPUT:
                //      1.) [0,0,1,0]   = [1,1,0,1]
                //      2.) [0,0,1,0]   = [2,2,0,2]
                //      3.) [1,1,0,1]   = [0,0,1,0]
                //
                //  As such, you'll notice position 1,0 (row 1, column 0) is 2, because this is the height of contiguous
                //  free space.
                for (int y = 0; y < gridSizeY; y++) {                
                    if(!invalidPoints[x, y]) {
                        hist[y] = 1 + hist[y];
                    } else {
                        hist[y] = 0;
                    }
                }
    
                // find the maximum size of the current histogram. If it happens to be larger
                // that the currently recorded max size, then it is the new max size.
                Vector2 maxSizeTemp = MaxRectSize(hist);
                int tempArea = (int)(maxSizeTemp.x * maxSizeTemp.y);
                if (tempArea > maxArea) {
                    maxSize = maxSizeTemp;
                    maxArea = tempArea;
                }
            }
    
            // at this point, we know the max size
            return maxSize;            
        }
    

    A few things to note about this:

    1. This version is meant for use with the Unity API. You can easily make this more generic by replacing instances of Vector2 with KeyValuePair. Vector2 is only used for a convenient way to store two values.
    2. invalidPoints[] is an array of bool, where true means the grid point is "in use", and false means it is not.

提交回复
热议问题