计算结构中的被困水

时间:2015-09-01 12:42:08

标签: python performance optimization out-of-memory space-complexity

假设我的输入是[1, 4, 2, 5, 1, 2, 3]。然后我们可以创建一个 像这样的结构:

...X...
.X.X...
.X.X..X
.XXX.XX
XXXXXXX
1425123

当所有地方的水倒在顶部并允许径流时, 它将被困在'O'位置:

...X...
.XOX...
.XOXOOX
.XXXOXX
XXXXXXX
1425123

我们必须在给定列表中找到被困'O'的总数。

我的程序能够给我正确的输出,但是当我运行它时 针对不同的测试用例,它给了我一个memory error。有什么办法可以减少这个程序的space complexity吗?

def answer(heights):
    row = len(heights)
    col = max(heights)
    sum = 0
    matrix = [['X' for j in range(i)] for i in heights]
    for i in range(col):
        rainWater = []
        for j in range(row):
            try:
                rainWater.append(matrix[j][i])
            except IndexError:
                rainWater.append('0')
        sum += ''.join(rainWater).strip('0').count('0')
    return sum

print answer([1, 4, 2, 5, 1, 2, 3])

列表数组至少包含1个元素,最多9000个元素。每个元素的值至少为1,最多为100000。

Inputs:
    (int list) heights = [1, 4, 2, 5, 1, 2, 3]

Output:
    (int) 5

Inputs:
    (int list) heights = [1, 2, 3, 2, 1]

Output:
    (int) 0

3 个答案:

答案 0 :(得分:3)

这可以通过以下方式在线性时间内以线性存储器要求求解:

def answer(heights):
    minLeft = [0] * len(heights)
    left = 0
    for idx, h in enumerate(heights):
        if left < h:
            left = h
        minLeft[idx] = left

    minRight = [0] * len(heights)
    right = 0
    for idx, h in enumerate(heights[::-1]):
        if right < h:
            right = h
        minRight[len(heights) - 1 - idx] = right

    water = 0
    for h, l, r in zip(heights, minLeft, minRight):
        water += min([l, r]) - h

    return water

如果在右侧或左侧分别有无限大小的墙,则数组minLeftminRight包含阵列中某个位置可以支持水的最高级别。然后在每个指数处,可以包含的总水量是左侧和右侧支撑的水位的最小值 - 地板的高度

此问题在更高维度处理此问题(将其与图像处理中的分水岭问题相关联):The Maximum Volume of Trapped Rain Water in 3D

答案 1 :(得分:1)

c#中的代码。 O(N)时间,O(1)空间。使用两个指针和2个整数变量进行跟踪。无法找出更优化的方式来解决这个问题。

     public int Trap(int[] height) {
    if(height == null || height.Length == 0)
      return 0;
    int max = 0;
    int vol = 0;
    int left = 0;
    int right = height.Length - 1;

    while(left<= right)
    {
        if(height[left] < height[right])
        {
            max = Math.Max(max,height[left]);
            vol = vol + (max-height[left]);
            left++;
        }
        else
        {
            max = Math.Max(max,height[right]);
            vol = vol + (max-height[right]);
            right--;
        }
    }
    return vol;
}

答案 2 :(得分:0)

您可以使用单个循环解决此问题(以下示例使用Java编写):

class LoginWidget(QtGui.QWidget):
    def __init__(self):
        super(Application, self).__init__()
        self.initUI() #Call Initialize UI function

    def initUI(self):
        self.showFullScreen()
        (...)

    class Admin(QtGui.QWidget):
    def __init__(self):
        super(Application, self).__init__()
        self.initUI() #Call Initialize UI function

    def initUI(self):
        self.showFullScreen()
        (...)