動機

每次看經典題與他的解答都是新的發現

這邊居然有dp 與 two pointer

Problem

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

 

Example 1:

Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]Output: 6Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

Example 2:

Input: height = [4,2,0,3,2,5]Output: 9

 

Constraints:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

Sol

一個會看到只要後面有更高的就可以把前面比較矮的給忽略掉,所以可以用stack存高到矮的牆,等高的出現,就可以一直pop算每一層的水

class Solution:
    def trap(self, hs: List[int]) -> int:
        stk = [] #premise: hs[stk[0]] > hs[stk[any i which is > 0]]
        ret = 0
        for i in range(len(hs)):
            if stk:
                if hs[stk[-1]] < hs[i]:
                    base_height = hs[stk.pop()] # pop bottom
                    while stk and hs[stk[-1]] <= hs[i]:
                        ret += (i-stk[-1]-1)*(min(hs[stk[-1]],hs[i])-base_height)
                        base_height = hs[stk.pop()]
                    if stk:
                        ret += (i-stk[-1]-1)*(min(hs[stk[-1]],hs[i])-base_height)
                elif hs[stk[-1]] == hs[i]:
                    stk.pop()
            stk.append(i)
            #print(i,stk,ret)
        return ret

或者是看成柱子一路長高的過程,再走的時候記下柱子與目前最高的差距

class Solution:
    def trap(self, hs: List[int]) -> int:
        a,b,ret = 0,len(hs)-1,0
        leftH, rightH = 0,0
        while a < b:
            if hs[a] < hs[b]:
                if hs[a] >= leftH:
                    leftH = hs[a]
                else:
                    ret += leftH-hs[a]
                a += 1
            else:
                if hs[b] >= rightH:
                    rightH = hs[b]
                else:
                    ret += rightH-hs[b]
                b -= 1
        return ret

但也不用兩邊都算,因為我們只要取最小的就好,所以只要累計左右最小的那一邊就好,如此一來就可以兩邊輪流算!! 就變成two pointer

class Solution:
    def trap(self, hs: List[int]) -> int:
        a,b,ret = 0,len(hs)-1,0
        leftH, rightH = 0,0
        while a < b:
            if hs[a] < hs[b]:
                if hs[a] >= leftH:
                    leftH = hs[a]
                else:
                    ret += leftH-hs[a]
                a += 1
            else:
                if hs[b] >= rightH:
                    rightH = hs[b]
                else:
                    ret += rightH-hs[b]
                b -= 1
        return ret