【发布时间】:2018-11-21 05:54:45
【问题描述】:
我一直在研究 Leetcode 上 problem 的不同算法,以 approach 1 开头。如果数组值为墙壁的高度,则该问题需要计算总水域面积(列宽 = 1)。
第一种方法是找到每根柱子左右两侧最大墙高中的最小高度,如果柱高小于最小值,则在给定柱子的顶部加水。取最小值,因为这是收集的水可以达到的最高值。要计算每一边的最大值,需要对左右进行n-1 遍历。
我用 Python 编写代码,但这里是 C++ 代码,按照Leetcode 上给出的解决方案。
int trap(vector<int>& height)
{
int ans = 0;
int size = height.size();
for (int i = 1; i < size - 1; i++) {
int max_left = 0, max_right = 0;
for (int j = i; j >= 0; j--) { //Search the left part for max bar size
max_left = max(max_left, height[j]);
}
for (int j = i; j < size; j++) { //Search the right part for max bar size
max_right = max(max_right, height[j]);
}
ans += min(max_left, max_right) - height[i];
}
return ans;
}
我注意到左右列的最大值包括外循环迭代中的当前列。这样可以得到的最小值是0。请确认这是正确的。我在0 和potentialWater 之间使用了min(),以收集到我的代码中。
我查看了代码并以自己的方式重写了它,但我得到了0,因为我收集的雨水总量应该得到6。我的代码中的错误在哪里?
class Solution:
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
if len(height) <= 2:
return 0
water = 0
for col in range(1, len(height)-1):
maxLeft = 0
maxRight = 0
for index in range(col):
maxLeft = max(maxLeft, height[index])
for index in range(col+1,len(height)):
maxRight = max(maxRight, height[index])
minHeight = min(maxLeft, maxRight)
# print(col, minHeight)
# minHeight = min(max(height[:col]), max(height[col+1:]))
potentialWater = minHeight - col
# print(potentialWater)
# water += potentialWater
water += max(0, potentialWater) # in case this is the highest column
return water
solution = Solution()
height = [0,1,0,2,1,0,1,3,2,1,2,1]
print(solution.trap(height))
【问题讨论】:
-
不知道这是否是您的问题,因为它是大量代码转储,但快速浏览一下,C++ 代码在内循环中包含
i,但您的 Python 代码是不包括等效内部循环中的col。你真的应该用惯用的 Python 重写这些东西(例如,maxRight = max(height[col:])),所以一开始就不会出现一个接一个的错误。 (顺便说一句,这在 C++ 中也是一个更好的答案……)但是,如果您真的想在与 C++ 代码相同的级别上做事,请确保您所做的完全相同。打印要比较的循环变量等。 -
@heretoinfinity 是的,这意味着复制列表的一半。但是对于许多现实生活中的问题,这并不重要——对于大多数性能很重要的现实生活中的问题,您应该使用 numpy 数组或类似的而不是列表(并且 numpy 数组在切片时返回就地视图) .如果您遇到 numpy 不适合但确实需要优化的一小部分问题,那么至少先让它工作,然后在工作后进行优化。
-
另外,在优化之前,测量。当然,如果列表很大,复制会很痛苦,甚至可能会破坏您的代码。但是,如果我们只讨论几千个元素,考虑到切片内的优化循环和单个
max调用与慢速通用for循环并一遍又一遍地调用max。 -
假设工作实际上是在Python中(使用CPython):如果您不仅可以指出切片副本,还可以解释如何使用
timeit和sys.getsizeof来比较权衡,那么我会印象深刻的。 (但能够猜出你从这些比较中得到的答案,我什至不会真正问任何人,除非他们声称自己是低级 Python 专家或其他人。)
标签: python c++ arrays algorithm