写写思路:存水一定是在两个峰中间,且两个最高峰之间存的水位一定是最高!
那我们就把峰高和峰位置记录下来成为list_top,
从最高到低遍历list_top:
如果当前峰在已经处理的峰之外(idx_top<l or idx>r),在当前峰和边界之间存水操作,直到遍历完所有的峰
否则不处理继续处理下一个峰。
所以需要用到双指针来确定已经处理过的峰,初始l=r=idx_top(-1)(最高峰)
class Solution(object):
def trap(self, height):
"""
:type height: List[int]
:rtype: int
先低再高能存水
先高再低为峰高
我维护一个数组,记录之前的峰,数组逆序排列【-1】为最小
!!!
错了错了,存水是在峰之间,所以要找峰
找到前两个峰然后双指针往外找
用不用找峰啊我感觉,找吧
"""
height.append(0)
sign=True
def takesec(gtitem):#这个函数用来给峰按照峰高排队
return gtitem[1]
def count_area(l,r,count,ans):#这个函数用来迭代list_top中的所有元素,是不是也可以写成循环啊?
if count!=-1:
if list_top[count][0]<l:
for i in range(list_top[count][0]+1,l):
if height[i]<height[list_top[count][0]]:
ans+=height[list_top[count][0]]-height[i]
l=list_top[count][0]
elif list_top[count][0]>r:
for i in range(r+1,list_top[count][0]):
if height[i]<height[list_top[count][0]]:
ans+=height[list_top[count][0]]-height[i]
r = list_top[count][0]
return count_area(l,r,count-1,ans)
else:
return ans
list_top=[]
for i in range(len(height)):#找峰,还是-1位置加一个0的老把戏,宽峰怎么办啊,峰宽真的可以忽略,相邻相等的两个峰就是一个0和两个0的区别
if height[i]>=height[i-1]:
sign=True
else:
if sign:
list_top.append([i-1,height[i-1]])
sign=False
list_top.sort(key=takesec)
if len(list_top)<2:#只有一个峰,直接返回0
return 0
else:
return count_area(list_top[-1][0],list_top[-1][0],len(list_top)-2,0)
写的代码太长了,双指针虽然是官方的一个题解,不过还有单调栈的思路我也想过,(为什么叫单调栈,栈顶的元素是未处理的最矮的栈)
如果碰到比栈顶高的峰,一直出栈,出栈的元素到当前元素的数值全部修改。
等等会放代码,还有没做完的每日一题