Skip to content

Commit 0a53786

Browse files
Chris WuChris Wu
Chris Wu
authored and
Chris Wu
committed
swim-in-rising-water.py
1 parent 89455fc commit 0a53786

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

problems/swim-in-rising-water.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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

Comments
 (0)