Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
866 views
in Technique[技术] by (71.8m points)

arrays - Largest rectangle of 1's in 2d binary matrix

There is a problem to find the maximum area of the 1 in the 0-1 matrix. In this problem there are two cases:

  1. area to be measure is of shape square. that's simple one by DP.

  2. area to be measure is of the shape of rectangle. i am not able to think a optimal solution for this.

Example:

010101
101001
111101
110101

The largest rectangle has an area of 4 (3rd row , 5th column and one more in 3rd,4th row). Can we also get all those rectangle ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'll step through a few solutions of increasing difficulty / decreasing runtime complexity.

First, a brute force solution. Generate every possible rectangle. You can do this by iterating through every pair of points (r1,c1) (r2,c2) with r1 ≤ r2 and c1 ≤ c2 (can be done with 4 for loops). If a rectangle does not contain a 0, you compare the area to the largest area found so far. This is an O(R^3C^3).

We can speed up the valid rectangle check to O(1). We do this by doing a DP where dp(r, c) stores the number of 0's in the rectangle ((1, 1), (r, c)).

  • dp(r, 0) = 0
  • dp(0, c) = 0
  • dp(r,c) = dp(r?1,c)+dp(r,c?1)?dp(r?1,c?1)+(matrix[r][c]?0:1)

Then the number of 0's in ((r1, c1), (r2, c2)) is

  • nzeroes(r1,c1,r2,c2) = dp[r2][c2]?dp[r1 ?1][c2]?dp[r2][c1 ?1]+dp[r1 ?1][c1 ?1]

You can then check if a rectangle is valid by nzeroes(r1,c1,r2,c2) == 0.

There is an O(R^2C) solution for this using a simple DP and a stack. The DP works per column, by finding the number of 1 cells above a cell until the next 0. The dp is as follows:

  • dp(r, 0) = 0
  • dp(r, c) = 0 if matrix[r][c] == 0
  • dp(r, c) = dp(r-1, c) + 1 otherwise

You then do the following:

area = 0
for each row r:
  stack = {}
  stack.push((height=0, column=0))
  for each column c:
    height = dp(r, c)
    c1 = c
    while stack.top.height > height:
      c1 = stack.top.column
      stack.pop()
    if stack.top.height != height:
      stack.push((height=height, column=c1))
    for item in stack:
      a = (c - item.column + 1) * item.height
      area = max(area, a)

It is also possible to solve the problem in O(RC) using three DP’s:

  • h(r, c): if we start at (r, c) and go upwards, how many 1 cells do we find before the first 0?
  • l(r, c): how far left can we extend a rectangle with bottom-right corner at (r, c) and height h(r, c)?
  • r(r,c): how far right can we extend a rectangle with bottom-left corner at (r, c) and height h(r, c)?

The three recurrence relations are:

  • h(0, c) = 0
  • h(r, c) = 0 if matrix[r][c] == 0
  • h(r, c) = h(r-1, c)+1 otherwise

  • l(r, 0) = 0

  • l(r, c) = c-p if matrix[r-1][c] == 0
  • l(r, c) = min(l(r ? 1, c), c ? p) otherwise

  • r(r,C+1) = 0

  • r(r,c) = p-c if matrix[r-1][c] == 0
  • r(r,c) = min(r(r ? 1, c), p ? c) otherwise

where p is the column of the previous 0 as we populate l from left-right and r from right-left.

The answer is then:

  • max_r,c(h(r, c) ? (l(r, c) + r(r, c) ? 1))

This works because of the observation that the largest rectangle will always touch a 0 (considering the edge as being covered in 0's) on all four sides. By considering all rectangles with at least top, left and right touching a 0, we cover all candidate rectangles. Generate every possible rectangle. You can do this by iterating through every pair of points (r1,c1) (r2,c2) with r1 ≤ r2 and c1 ≤ c2 (can be done with 4 for loops). If a rectangle does not contain a 0, you compare the area to the largest area found so far.

Note: I adapted the above from an answer I wrote up here - refer to the section "Ben's Mom". In that writeup, the 0's are trees. That writeup also has better formatting.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...