看到这道题目,我的思路起始于从左到右遍历,但是没有left_max和right_max的概念,完全实施不了具体的算法。
而是转换思路,从下到上遍历,但是这种又需要每次从左到右遍历,而且在左右两端的判断我也不清楚如何进行。遂放弃。
成熟的两种思路第一种思路完全依赖于left_max和right_max的概念,一旦确定概念只是如何计算的问题(除了从左到右遍历计算还有就是通过类似于数学归纳法的计算方式进行计算)。
第二种思路,部分依赖于left_max和right_max的概念,但是处理起来更具技巧,通过height[left]和height[right]的比较,从而每个节点只需要left_max或right_max中的一个就可以确定积水量。而且也不占空间。
思路1:
对每一个节点i计算在其左边最大的left_max[i]和在其右边最大的right_max[i]。
然后通过计算下列式子从1遍历到n-1累加得到res。
max(0, min(left_max[i], right_max[i])-height[i])
通过left_max, right_max记录,分别从左到右和从右到左依次计算(有些类似数列中数学归纳法的思想)
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
n = len(height)
res = 0
if n<=2:
return res
left_max = [0]*n
right_max = [0]*n
for i in range(1,n-1):
left_max[i] = max(left_max[i-1],height[i-1])
for i in range(n-2,0,-1):
right_max[i] = max(right_max[i+1], height[i+1])
for i in range(1, n-1):
res += max(0, min(left_max[i], right_max[i])-height[i])
return res
思路2:
在数组中常用的左右夹逼,在height[l] < height[r]的情况下,要么更新left_max要么计算l节点的储水量。
一开始我的思路也靠近这一种,但是一是没有left_max的概念在,而是不知道如何分类讨论。
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
n = len(height)
res = 0
if n<=2:
return res
l = 0
r = n-1
left_max = height[0]
right_max = height[n-1]
while l<r:
if height[l]<height[r]:
if height[l]>=left_max:
left_max=height[l]
else:
res += left_max - height[l]
l += 1
else:
if height[r] >= right_max:
right_max = height[r]
else:
res += right_max - height[r]
r -= 1
return res