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

前端 未结 8 2192
伪装坚强ぢ
伪装坚强ぢ 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条回答
  •  孤独总比滥情好
    2020-11-22 06:45

    Here is a version of jfs' solution, which also delivers the position of the largest rectangle:

    from collections import namedtuple
    from operator import mul
    
    Info = namedtuple('Info', 'start height')
    
    def max_rect(mat, value=0):
        """returns (height, width, left_column, bottom_row) of the largest rectangle 
        containing all `value`'s.
    
        Example:
        [[0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
         [0, 4, 0, 2, 4, 0, 0, 1, 0, 0],
         [1, 0, 1, 0, 0, 0, 3, 0, 0, 4],
         [0, 0, 0, 0, 4, 2, 0, 0, 0, 0],
         [0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
         [4, 3, 0, 0, 1, 2, 0, 0, 0, 0],
         [3, 0, 0, 0, 2, 0, 0, 0, 0, 4],
         [0, 0, 0, 1, 0, 3, 2, 4, 3, 2],
         [0, 3, 0, 0, 0, 2, 0, 1, 0, 0]]
         gives: (3, 4, 6, 5)
        """
        it = iter(mat)
        hist = [(el==value) for el in next(it, [])]
        max_rect = max_rectangle_size(hist) + (0,)
        for irow,row in enumerate(it):
            hist = [(1+h) if el == value else 0 for h, el in zip(hist, row)]
            max_rect = max(max_rect, max_rectangle_size(hist) + (irow+1,), key=area)
            # irow+1, because we already used one row for initializing max_rect
        return max_rect
    
    def max_rectangle_size(histogram):
        stack = []
        top = lambda: stack[-1]
        max_size = (0, 0, 0) # height, width and start position of the largest rectangle
        pos = 0 # current position in the histogram
        for pos, height in enumerate(histogram):
            start = pos # position where rectangle starts
            while True:
                if not stack or height > top().height:
                    stack.append(Info(start, height)) # push
                elif stack and height < top().height:
                    max_size = max(max_size, (top().height, (pos - top().start), top().start), key=area)
                    start, _ = stack.pop()
                    continue
                break # height == top().height goes here
    
        pos += 1
        for start, height in stack:
            max_size = max(max_size, (height, (pos - start), start), key=area)
    
        return max_size
    
    def area(size):
        return size[0] * size[1]
    

提交回复
热议问题