1326. Minimum Number of Taps to Open to Water a Garden - cocoder39/coco39_LC GitHub Wiki

1326. Minimum Number of Taps to Open to Water a Garden

Option 0: O(n) greedy

template

class Solution:
    def minTaps(self, n: int, ranges: List[int]) -> int:
        taps = []
        for i, r in enumerate(ranges):
            left, right = max(0, i-r), min(n, i+r)
            taps.append([left, right])
        taps.sort()
        
        curEnd, nextEnd = 0, 0
        cnt = 0
        for left, right in taps:
            if nextEnd < left:
                return -1
            
            if curEnd < left:
                cnt += 1
                curEnd = nextEnd
                if curEnd >= n:
                    return cnt
            
            nextEnd = max(nextEnd, right)
        
        if nextEnd < left:
            return -1
        
        if curEnd >= n:
            return cnt
        return cnt + 1

pretty much 45. Jump Game II

Option 1: greedy

why for i in range(n): instead of for i in range(n+1): at the point i == n-1, there are 3 cases:

  1. curMaxPos < n-1: return -1
  2. curMaxPos == n-1: return count+1
  3. curMaxPos > n-1: return count
class Solution:
    def minTaps(self, n: int, ranges: List[int]) -> int:
        nextIdx = [-1] * (n+1)
        for i, r in enumerate(ranges):
            left = max(i-r, 0)
            nextIdx[left] = max(nextIdx[left], i+r)
        
        count = 0
        curMaxPos = nextMaxPos = 0
        for i in range(n):
            nextMaxPos = max(nextMaxPos, nextIdx[i])
            if curMaxPos < i:
                return -1
            elif curMaxPos == i:
                count += 1
                curMaxPos = nextMaxPos
        return count

Option 2: DP

initialize dp to n+2 as the max number we need is n+1 so n+2 means unreachable

dp[i] : min number of taps required to water range [0: i+1]

dp[j] = min(dp[j], dp[left] + 1) => there might be position x between left and j where we can add this tap to water j. However, dp[x] >= dp[left]

class Solution:
    def minTaps(self, n: int, ranges: List[int]) -> int:
        dp = [0] + [n+2] * n
        for i, r in enumerate(ranges):
            left, right = max(i-r, 0), min(i+r, n)
            for j in range(left+1, right+1):
                dp[j] = min(dp[j], dp[left] + 1)
        return dp[-1] if (dp[-1] < n+2) else -1