【问题标题】:Obtain location of largest rectangle获取最大矩形的位置
【发布时间】:2021-07-26 18:33:07
【问题描述】:

我正在尝试按照此处答案中的代码进行操作:Find largest rectangle containing only zeros in an N×N binary matrix

我很难理解如何找到算法找到的最大矩形的原点(x,y)

来自收藏

import namedtuple
from operator import mul
import numpy as np
import functools

x = np.zeros(shape=(4,5))
x[0][0] = 1
x[0][1] = 1
x[0][2] = 1
x[0][3] = 1
x[1][0] = 1
x[1][1] = 1
x[1][2] = 1
x[1][3] = 1
print(x)
print(max_size(x))

Info = namedtuple('Info', 'start height')

def find_maximum_frame(mat, value=1):
    """Find height, width of the largest rectangle containing all `value`'s."""
    it = iter(mat)
    hist = [(el==value) for el in next(it, [])]
    max_size, _ = max_rectangle_size(hist)
    old_size = (0,0)
    coordinates = None
    for y,row in enumerate(it):
        hist = [(1+h) if el == value else 0 for h, el in zip(hist, row)]
        new_rect, c = max_rectangle_size(hist)
        max_size = max(max_size, new_rect, key=area)
        if max_size[0]*max_size[1] > old_size[0]*old_size[1]:
            coordinates = [c[0], (y+2)-max_size[0]]
        old_size = max_size
    return [max_size, coordinates]

def max_rectangle_size(histogram):
    """Find height, width of the largest rectangle that fits entirely under
    the histogram.
    """
    stack = []
    top = lambda: stack[-1]
    max_size = (0, 0) # height, width 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
                print(stack)
            elif stack and height < top().height:
                max_size = max(max_size, (top().height, (pos - top().start)),
                               key=area)
                start, _ = stack.pop()
                continue
            break # height == top().height goes here

    pos += 1
    coordinates = [0,0]
    old_size = (0,0)
    for start, height in stack:
        max_size = max(max_size, (height, (pos - start)), key=area)
        if max_size[0]*max_size[1] > old_size[0]*old_size[1]:
            coordinates = [start,height]
        old_size = max_size
    return [max_size, coordinates]

def area(size):
    return functools.reduce(mul, size)

在我的示例中,上面的代码似乎可以找到矩形的左上角,但是当我在更大的图像上尝试它时,它会崩溃并且我无法调试原因。

【问题讨论】:

  • if sum(max_size) &gt; sum(old_max): 行不正确,因为 sum 没有给你区域。您需要服用该产品。要获得 x 坐标,您必须从 max_rectangle_size 返回它。
  • @LawrenceWu 是的,我实际上在本地进行了更改,但忘记编辑我的问题。即使在一个简单的例子中,这似乎也不能正常工作。编辑了我的问题以包含示例。
  • 我还没有运行你的代码,但看起来它会返回矩形的底部(最大的 y 坐标)。这不是会发生什么吗?
  • @LawrenceWu 刚刚将我的代码更新为可运行
  • @LawrenceWu 当我在初始 while 循环之后执行 print(stack) 时,我会一遍又一遍地重复 [Info(start=0, height=0)]

标签: python algorithm


【解决方案1】:

这里有一个修改 J.F. Sebastian 的answerGist version 的解决方案:

from collections import namedtuple

Info = namedtuple('Info', 'start height')

# returns height, width, and position of the top left corner of the largest
#  rectangle with the given value in mat
def max_size(mat, value=0):
    it = iter(mat)
    hist = [(el==value) for el in next(it, [])]
    max_size_start, start_row = max_rectangle_size(hist), 0
    for i, row in enumerate(it):
        hist = [(1+h) if el == value else 0 for h, el in zip(hist, row)]
        mss = max_rectangle_size(hist)
        if area(mss) > area(max_size_start):
            max_size_start, start_row = mss, i+2-mss[0]
    return max_size_start[:2], (start_row, max_size_start[2])

# returns height, width, and start column of the largest rectangle that
#  fits entirely under the histogram
def max_rectangle_size(histogram):
    stack = []
    top = lambda: stack[-1]
    max_size_start = (0, 0, 0) # height, width, start 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_start = max(
                    max_size_start,
                    (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_start = max(max_size_start, (height, pos - start, start),
            key=area)

    return max_size_start

def area(size): return size[0]*size[1]

一旦将位置添加到测试中,代码就会通过Gist version 中的所有测试。这里,例如,第一个测试:

    self.assertEqual(max_size(self.__s2m("""
    0 0 0 0 1 0
    0 0 1 0 0 1
    0 0 0 0 0 0
    1 0 0 0 0 0
    0 0 0 0 0 1
    0 0 1 0 0 0""")), ((3, 4), (2, 1)))

大小为 (3, 4) 的矩形位于位置 (2, 1)。

【讨论】:

  • 是的,我最终分别得出了相同的确切结论。不过你得到了赏金:)
  • 我使用了 Gist 代码,因为这看起来更安全,并且在完成后,注意到您的代码很接近。 :) 顺便说一句,我快速查看scipy.ndimageOpenCV是否有这个,但没有运气。使用(更多)本机代码来解决这个问题应该会带来很好的加速......
【解决方案2】:

这里是hackerrank同样问题的解决方案...

public static long largestRectangle(List<Integer> h) {
// Write your code here
Stack<Integer> st1 = new Stack<>();
int i = 0;
int topIndex = 0;
long area;
long finalArea=0;
while(i<h.size()){
  if(st1.isEmpty() || h.get(st1.peek()) <= h.get(i)){
    st1.push(i++);
  }else{
    topIndex = st1.peek();
    st1.pop();
    
    area = h.get(topIndex) * (st1.isEmpty() ? i : i-1-st1.peek());
    if(area > finalArea ){
      finalArea = area;
    }
  }
}
while(st1.isEmpty()==false){
  topIndex = st1.peek();
  st1.pop();
  area = h.get(topIndex) * (st1.isEmpty() ? i : i-1-st1.peek());
    if(area > finalArea ){
      finalArea = area;
    }
}
return finalArea;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多