|
| 1 | +""" |
| 2 | +Starting from `(0, 0)` we keep on selecting the neighbor with lower elevation until we reach the end. |
| 3 | +There are four possible neighbors `(i+1, j), (i-1, j), (i, j+1), (i, j-1)`. |
| 4 | +Every time we select neighbor we check if we visited and choose the smallest elevation to go. |
| 5 | +""" |
| 6 | +#Wrong |
| 7 | +class Solution(object): |
| 8 | + def swimInWater(self, grid): |
| 9 | + def getNext(i, j): |
| 10 | + options = [(i+1, j), (i-1, j), (i, j+1), (i, j-1)] |
| 11 | + elevation = float('inf') |
| 12 | + opt = (None, None) |
| 13 | + for i_next, j_next in options: |
| 14 | + if i_next<0 or i_next>=N or j_next<0 or j_next>=M: continue |
| 15 | + if (i_next, j_next) in visited: continue |
| 16 | + if grid[i_next][j_next]<elevation: |
| 17 | + elevation = grid[i_next][j_next] |
| 18 | + opt = (i_next, j_next) |
| 19 | + return opt |
| 20 | + |
| 21 | + N = len(grid) |
| 22 | + M = len(grid[0]) |
| 23 | + ans = grid[-1][-1] |
| 24 | + visited = set() |
| 25 | + i = j = 0 |
| 26 | + |
| 27 | + while i<N-1 and j<M-1: |
| 28 | + print i, j |
| 29 | + visited.add((i, j)) |
| 30 | + ans = max(ans, grid[i][j]) |
| 31 | + i, j = getNext(i, j) |
| 32 | + return ans |
| 33 | + |
| 34 | +""" |
| 35 | +The above solution is worng, because we might reach a point which all its neighbor is visited (dead end). |
| 36 | +That is why we need a heap to get the next posible point to go. |
| 37 | +And when we reach dead end, we pop out the next avaliable option. |
| 38 | +The time complexity is O((N^2)*LogN), for there are N^2 point and every heap operation for it is LogN. |
| 39 | +Space complexity is O(N^2) |
| 40 | +""" |
| 41 | +#Heap solution |
| 42 | +class Solution(object): |
| 43 | + def swimInWater(self, grid): |
| 44 | + ans = grid[-1][-1] |
| 45 | + N = len(grid) |
| 46 | + pq = [] |
| 47 | + seen = set() |
| 48 | + |
| 49 | + heapq.heappush(pq, (grid[0][0], 0, 0)) |
| 50 | + while pq: |
| 51 | + t, i, j = heapq.heappop(pq) |
| 52 | + ans = max(ans, t) |
| 53 | + if i==N-1 and j==N-1: return ans |
| 54 | + for i_next, j_next in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: |
| 55 | + if i_next<0 or i_next>=N or j_next<0 or j_next>=N: continue |
| 56 | + if (i_next, j_next) in seen: continue |
| 57 | + heapq.heappush(pq, (grid[i_next][j_next], i_next, j_next)) |
| 58 | + seen.add((i_next, j_next)) |
| 59 | + return ans |
| 60 | + |
| 61 | + |
| 62 | +""" |
| 63 | +The answer must lie between `l` and `h`. |
| 64 | +Where h is the value we sure that it can pass, l is the value it might or might not pass. |
| 65 | +So we gradually test the value between `l~h` by binary search. |
| 66 | +Until we find the value which is the lowest possible time that can pass. #[0] |
| 67 | +
|
| 68 | +I init the `l` with the `t` of the destination, because we couldn't have been reach the destination without using `t` amount of time. |
| 69 | +I init the `h` with the max `t` in the entire grid, since we can swim withim this time no matter what. |
| 70 | +
|
| 71 | +The function `canPassWtihTimeLimit(t)` takes a parameter `t` and use DFS to see if we can swim to the destination in the time limit t. |
| 72 | +
|
| 73 | +The time complexity is O((N^2)*LogN). |
| 74 | +Find the max in the grid took O(N^2). |
| 75 | +`canPassWtihTimeLimit(t)` took O(N^2), because we might possibly travel the entire grid. |
| 76 | +We call `canPassWtihTimeLimit(t)` about O(LogN) of time because we use the binary search concept to navigate the `l` and `r`. |
| 77 | +""" |
| 78 | +class Solution(object): |
| 79 | + def swimInWater(self, grid): |
| 80 | + def canPassWtihTimeLimit(t): |
| 81 | + stack = [] |
| 82 | + seen = set() |
| 83 | + |
| 84 | + if grid[0][0]<=t: stack.append((0, 0)) |
| 85 | + while stack: |
| 86 | + i, j = stack.pop() |
| 87 | + if i==N-1 and j==N-1: return True |
| 88 | + seen.add((i, j)) |
| 89 | + for i_next, j_next in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: |
| 90 | + if i_next<0 or i_next>=N or j_next<0 or j_next>=N: continue |
| 91 | + if (i_next, j_next) in seen: continue |
| 92 | + if grid[i_next][j_next]>t: continue |
| 93 | + stack.append((i_next, j_next)) |
| 94 | + return False |
| 95 | + |
| 96 | + N = len(grid) |
| 97 | + l = grid[-1][-1] |
| 98 | + h = max(map(max, grid)) #get max value in the grid |
| 99 | + while True: |
| 100 | + m = (l+h)/2 |
| 101 | + p = canPassWtihTimeLimit(m) |
| 102 | + if p and not canPassWtihTimeLimit(m-1): return m #[0] |
| 103 | + if p: |
| 104 | + h = m |
| 105 | + else: |
| 106 | + l = m+1 |
| 107 | + return h |
| 108 | + |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | + |
0 commit comments