Skip to content

Commit 13fbec9

Browse files
committed
no message
1 parent 5dda17b commit 13fbec9

14 files changed

+493
-5
lines changed

problems/campus-bikes-ii.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
state[i] := ith bike has been selected.
3+
For example, there are M bikes, 0000, 0100, 0110, 1111.....
4+
5+
Time: O(ELogE)
6+
Space: O(E)
7+
"""
8+
class Solution(object):
9+
def assignBikes(self, workers, bikes):
10+
M = len(bikes)
11+
N = len(workers)
12+
costs = [[0]*N for _ in xrange(M)]
13+
14+
for i in xrange(M):
15+
for j in xrange(N):
16+
costs[i][j] = abs(workers[j][0]-bikes[i][0])+abs(workers[j][1]-bikes[i][1])
17+
18+
pq = [(0, '0'*M)]
19+
visited = set()
20+
while pq:
21+
cost, state = heapq.heappop(pq)
22+
if state in visited: continue
23+
visited.add(state)
24+
25+
j = state.count('1') #j users have selected bikes
26+
if j>=N: return cost
27+
28+
for i in xrange(M):
29+
if state[i]=='1': continue
30+
31+
nextState = state[:i] + '1' + state[i+1:]
32+
if nextState in visited: continue
33+
heapq.heappush(pq, (cost+costs[i][j], nextState))
34+
35+
return float('inf')

problems/construct-binary-tree-from-inorder-and-postorder-traversal.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,35 @@ def helper(i, j, k, l):
6868

6969
index = {} #the index of inorder
7070
for i, n in enumerate(inorder): index[n] = i
71-
return helper(0, len(inorder), 0, len(postorder))
71+
return helper(0, len(inorder), 0, len(postorder))
72+
73+
74+
75+
76+
77+
"""
78+
Inorder: [LEFT]root[RIGHT]
79+
Postorder: [LEFT][RIGHT]root
80+
As you can see, rootVal is the last val in postorder.
81+
82+
i and j is the range of the inorder
83+
k and l is the range of the postorder
84+
Get the root
85+
Also recursively use the same method to get the left and right node, but this time we change the inorder and postorder.
86+
"""
87+
class Solution(object):
88+
def buildTree(self, inorder, postorder):
89+
def helper(i, j, k, l):
90+
if i>j or k>l: return None
91+
rootVal = postorder[l]
92+
root = TreeNode(rootVal)
93+
r = inorderIndex[rootVal]
94+
leftLength = r-i
95+
rightLength = j-r
96+
root.left = helper(i, r-1, k, k+leftLength-1)
97+
root.right = helper(r+1, j, k+leftLength, k+leftLength+rightLength-1)
98+
return root
99+
100+
inorderIndex = {}
101+
for i, n in enumerate(inorder): inorderIndex[n] = i
102+
return helper(0, len(inorder)-1, 0, len(postorder)-1)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution(object):
2+
def flipMatchVoyage(self, root, voyage):
3+
def helper(node):
4+
if not node: return
5+
if node.val!=voyage[self.i]:
6+
self.valid = False
7+
return
8+
9+
self.i += 1
10+
if node.left and node.left.val!=voyage[self.i]:
11+
self.ans.append(node.val)
12+
helper(node.right)
13+
helper(node.left)
14+
15+
else:
16+
helper(node.left)
17+
helper(node.right)
18+
19+
self.ans = []
20+
self.i = 0
21+
self.valid = True
22+
helper(root)
23+
return self.ans if self.valid else [-1]

problems/kth-largest-element-in-an-array.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,34 @@ def partition(A, l, r, p):
6363

6464
k = len(nums)-k #redefine the problem to find the kth nums when sorted
6565
sortRange(nums, 0, len(nums)-1)
66-
return nums[k]
66+
return nums[k]
67+
68+
69+
#Quick Select
70+
class Solution(object):
71+
def findKthLargest(self, nums, K):
72+
def quickSelect(A, s, e, K):
73+
pivot = A[(s+e)/2]
74+
i = s
75+
t = s
76+
j = e
77+
78+
while t<=j:
79+
if A[t]<pivot:
80+
A[i], A[t] = A[t], A[i]
81+
i += 1
82+
t += 1
83+
elif A[t]==pivot:
84+
t += 1
85+
else:
86+
A[t], A[j] = A[j], A[t]
87+
j -= 1
88+
89+
if e-j>=K:
90+
return quickSelect(A, j+1, e, K)
91+
elif e-i+1>=K:
92+
return pivot
93+
else:
94+
return quickSelect(A, s, i-1, K-(e-(i-1)))
95+
96+
return quickSelect(nums, 0, len(nums)-1, K)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
Time: O(ELogE), E is the edge of the graph.
3+
Note that state[i] means if the ith student is matched or not. (for example M=4, 0000, 0010, 0111, 1111...)
4+
2^M is the number of states. So in this case E will be 2^M x M.
5+
6+
Space: O(2^M)
7+
"""
8+
class Solution(object):
9+
def maxCompatibilitySum(self, students, mentors):
10+
M = len(students)
11+
N = len(students[0])
12+
13+
#initialize reverseScores
14+
reverseScores = [[0]*M for _ in xrange(M)]
15+
for i in xrange(M):
16+
for j in xrange(M):
17+
reverseScore = 0
18+
for k in xrange(N):
19+
if students[i][k]!=mentors[j][k]:
20+
reverseScore += 1
21+
reverseScores[i][j] = reverseScore
22+
23+
#Dijkstra
24+
startState = '0'*M
25+
endState = '1'*M
26+
visited = set()
27+
pq = [(0, startState)]
28+
29+
while pq:
30+
cost, state = heapq.heappop(pq)
31+
if state in visited: continue
32+
visited.add(state)
33+
34+
if state==endState: return M*N-cost
35+
36+
j = state.count('1')
37+
for i in xrange(M):
38+
if state[i]=='1': continue
39+
40+
nextState = state[:i]+'1'+state[i+1:]
41+
if nextState in visited: continue
42+
heapq.heappush(pq, (cost+reverseScores[i][j], nextState))
43+
44+
return -1
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Solution(object):
2+
def minCost(self, grid):
3+
pq = [(0, False, 0, 0, 0)]
4+
visited = set()
5+
M = len(grid)
6+
N = len(grid[0])
7+
8+
while pq:
9+
cost, modified, direction, x, y = heapq.heappop(pq)
10+
if x<0 or x>=M or y<0 or y>=N: continue
11+
if (direction, x, y) in visited: continue
12+
visited.add((direction, x, y))
13+
14+
if x==M-1 and y==N-1: return cost
15+
16+
if direction==0: direction = grid[x][y]
17+
18+
if direction==1:
19+
heapq.heappush(pq, (cost, False, 0, x, y+1))
20+
elif direction==2:
21+
heapq.heappush(pq, (cost, False, 0, x, y-1))
22+
elif direction==3:
23+
heapq.heappush(pq, (cost, False, 0, x+1, y))
24+
elif direction==4:
25+
heapq.heappush(pq, (cost, False, 0, x-1, y))
26+
27+
if not modified:
28+
for d in [1,2,3,4]:
29+
if d==grid[x][y]: continue
30+
heapq.heappush(pq, (cost+1, True, d, x, y))
31+
32+
return float('inf')
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""
2+
state[i] := nums1[i] has been matched.
3+
"""
4+
class Solution(object):
5+
def minimumXORSum(self, nums1, nums2):
6+
N = len(nums1)
7+
8+
pq = [(0, '0'*N)]
9+
visited = set()
10+
while pq:
11+
s, state = heapq.heappop(pq)
12+
if state in visited: continue
13+
visited.add(state)
14+
15+
j = state.count('1')
16+
if j==N: return s
17+
18+
for i in xrange(N):
19+
if state[i]=='1': continue
20+
nextState = state[:i]+'1'+state[i+1:]
21+
if nextState in visited: continue
22+
heapq.heappush(pq, ((s+(nums1[i]^nums2[j-1]), nextState)))
23+
24+
return float('inf')

problems/network-delay-time.py

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,96 @@ def networkDelayTime(self, times, n, k):
118118

119119

120120

121+
"""
122+
Dijkstra BFS+Priority Queue Implementation
123+
Time: O(ELogE), E is the edges count in the graph.
124+
"""
125+
class Solution(object):
126+
def networkDelayTime(self, times, N, K):
127+
ans = -1 #max time from K to any
128+
visited = set()
129+
pq = [(0, K)] #[(node's distance to K, node)]
130+
131+
#construct adjacency list
132+
adj = collections.defaultdict(list)
133+
for u, v, w in times:
134+
adj[u].append((w, v))
135+
136+
while pq:
137+
dis, node = heapq.heappop(pq)
138+
if node in visited: continue
139+
visited.add(node)
140+
141+
ans = max(ans, dis)
142+
143+
for d2, nei in adj[node]:
144+
heapq.heappush(pq, (d2+dis, nei))
145+
146+
return ans if len(visited)==N else -1
121147

122148

123149

150+
"""
151+
Dijkstra Normal Implementation
152+
Time: O(N^2), N is the nodes count in the graph.
153+
"""
154+
class Solution(object):
155+
def networkDelayTime(self, times, N, K):
156+
#construct dis. dis[n] := node n distance to K
157+
dis = {}
158+
for n in xrange(1, N+1):
159+
dis[n] = float('inf')
160+
dis[K] = 0
161+
162+
visited = set()
163+
164+
#construct adjacency list
165+
adj = collections.defaultdict(list)
166+
for u, v, w in times:
167+
adj[u].append((w, v))
168+
124169

170+
while len(visited)<N:
171+
#find the nearest node to K, lets call it minDisNode
172+
minDisNode = None
173+
minDis = float('inf')
174+
175+
for n in xrange(1, N+1):
176+
if n not in visited and dis[n]<minDis:
177+
minDisNode = n
178+
minDis = dis[n]
179+
180+
#update minDisNode neighbor's distance to K
181+
if minDis==float('inf'): break
182+
for d2, nei in adj[minDisNode]:
183+
dis[nei] = min(dis[nei], d2+minDis)
184+
185+
#store the node we alreay determined the distance to K in visited
186+
visited.add(minDisNode)
187+
188+
return max(dis.values()) if len(visited)==N else -1
125189

126190

127-
128-
129-
191+
"""
192+
Floyd
193+
Time: O(N^3), N is the nodes count in the graph.
194+
Note that Floyed can calculate the shortest distance between any two nodes.
195+
Also, it can handle negative values on the edge.
196+
"""
197+
class Solution(object):
198+
def networkDelayTime(self, times, N, K):
199+
#dp[i-1][j-1] := distance from i to j
200+
dp = [[float('inf') for i in xrange(1, N+1)] for j in xrange(1, N+1)]
201+
202+
for i in xrange(1, N+1):
203+
dp[i-1][i-1] = 0
204+
for u, v, w in times:
205+
dp[u-1][v-1] = w
206+
207+
for k in xrange(1, N+1):
208+
for i in xrange(1, N+1):
209+
for j in xrange(1, N+1):
210+
dp[i-1][j-1] = min(dp[i-1][j-1], dp[i-1][k-1]+dp[k-1][j-1])
211+
212+
ans = max(dp[K-1])
213+
return ans if ans!=float('inf') else -1
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class Solution(object):
2+
def countPaths(self, n, roads):
3+
def countWaysToReach(node):
4+
if node==0: return 1
5+
if node in history: return history[node]
6+
c = 0
7+
for nei, t in adj[node]:
8+
if nei in times and times[nei]+t==times[node]:
9+
c += countWaysToReach(nei)
10+
history[node] = c
11+
return c
12+
13+
history = {} #cache for countWaysToReach()
14+
times = {} #min times to reach node n-1
15+
pq = [(0, 0)]
16+
17+
adj = collections.defaultdict(list)
18+
for u, v, t in roads:
19+
adj[u].append((v, t))
20+
adj[v].append((u, t))
21+
22+
while pq:
23+
t, node = heapq.heappop(pq)
24+
if node in times: continue
25+
times[node] = t
26+
27+
if node==n-1: break
28+
29+
for nei, t2 in adj[node]:
30+
if nei in times: continue
31+
heapq.heappush(pq, (t+t2, nei))
32+
33+
return countWaysToReach(n-1)%(10**9 + 7)

0 commit comments

Comments
 (0)