Skip to content

Commit 216d4af

Browse files
author
Chris Wu
committed
no message
1 parent b0c1249 commit 216d4af

File tree

3 files changed

+87
-38
lines changed

3 files changed

+87
-38
lines changed

problems/course-schedule-ii.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from collections import defaultdict, deque
2+
3+
class Solution(object):
4+
def findOrder(self, numCourses, prerequisites):
5+
graph = defaultdict(list)
6+
inbound = defaultdict(int)
7+
q = deque()
8+
order = deque()
9+
10+
#building graph as adjacency list
11+
for c1, c2 in prerequisites:
12+
graph[c2].append(c1)
13+
inbound[c1] += 1
14+
15+
#find the starting point
16+
for c in xrange(numCourses):
17+
if inbound[c]==0:
18+
q.append(c)
19+
20+
#traverse the directed graph
21+
while q:
22+
c = q.popleft()
23+
24+
for nei in graph[c]:
25+
inbound[nei] -= 1
26+
if inbound[nei]==0:
27+
q.append(nei)
28+
29+
order.append(c)
30+
31+
return order if len(order)==numCourses else []
32+
33+
"""
34+
Topological sort works only in directed graph.
35+
We can use it to know which node comes after which or detect cycles.
36+
The algorithm is easy to understand.
37+
First, we build the adjacent list (`graph`) and count all the inbound of the node.
38+
Then we start from the node whose inbound count is 0, adding it in to the `q`.
39+
For every node we pop out from `q`
40+
* We remove the node's outbound by decrease 1 on all its neighbor's inbound.
41+
* Put the node's neighbor to `q` if it has no inbound
42+
* Put the node into the `order`
43+
Repeat the process until there is no more node.
44+
The order in the `order` is the order we are going to encounter when we run through the directed graph.
45+
If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph.
46+
47+
Time: O(E+2V) ~= O(E+V)
48+
we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3].
49+
Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`.
50+
"""

problems/course-schedule.py

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,3 @@
1-
"""
2-
First, we build a graph of adjacency list #[0]
3-
0->[2,4,5]
4-
1->[3,4]
5-
Meaning before taking 2,4,5 we need to take 0, before taking 3,4 we need to take 1
6-
if we find a loop back to itself then it is impossible, for example
7-
0->[2,4,5]
8-
1->[3,4]
9-
2->[0,3]
10-
0->2->0, which is imposible.
11-
12-
Now we iterate every course to see if it can loop back to itself in anyway #[1]
13-
we do this by dfs and search for it self
14-
if we find itself we find loop
15-
16-
The time efficiency is O(V^2+VE), because each dfs in adjacency list is O(V+E) and we do it V times
17-
Space efficiency is O(E).
18-
V is the numCourses (Vertices).
19-
E is the number of prerequisites (Edges).
20-
"""
211
class Solution(object):
222
def canFinish(self, numCourses, prerequisites):
233
graph = {n:[] for n in xrange(numCourses)} #[0]
@@ -36,25 +16,27 @@ def canFinish(self, numCourses, prerequisites):
3616
if ajc not in visited:
3717
stack.append(ajc)
3818
return True
39-
4019
"""
41-
Topological sort works only in directed graph.
42-
We can use it to know which node comes after which or detect cycles.
43-
The algorithm is easy to understand.
44-
First, we build the adjacent list and count all the inbound of the node.
45-
Then we start from the node whose inbound count is 0, adding it in to the `q_next`.
46-
For every node we pop out from q_next
47-
* We remove the node's outbound by decrease 1 on all its neighbor's inbound.
48-
* Put the node's neighbor to `q_next` if it has no inbound
49-
* Put the node into the `q`
50-
Repeat the process until there is no more node.
51-
The order in the `q` is the order we are going to encounter when we run through the directed graph.
52-
If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph.
20+
First, we build a graph of adjacency list #[0]
21+
0->[2,4,5]
22+
1->[3,4]
23+
Meaning before taking 2,4,5 we need to take 0, before taking 3,4 we need to take 1
24+
if we find a loop back to itself then it is impossible, for example
25+
0->[2,4,5]
26+
1->[3,4]
27+
2->[0,3]
28+
0->2->0, which is imposible.
5329
54-
Time: O(E+2V) ~= O(E+V)
55-
we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3].
56-
Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`.
30+
Now we iterate every course to see if it can loop back to itself in anyway #[1]
31+
we do this by dfs and search for it self
32+
if we find itself we find loop
33+
34+
The time efficiency is O(V^2+VE), because each dfs in adjacency list is O(V+E) and we do it V times
35+
Space efficiency is O(E).
36+
V is the numCourses (Vertices).
37+
E is the number of prerequisites (Edges).
5738
"""
39+
5840
class Solution(object):
5941
def canFinish(self, numCourses, prerequisites):
6042
graph = collections.defaultdict(list)
@@ -78,5 +60,22 @@ def canFinish(self, numCourses, prerequisites):
7860
q_next.append(nei)
7961
q.append(n)
8062
return len(q)==numCourses
63+
64+
"""
65+
Topological sort works only in directed graph.
66+
We can use it to know which node comes after which or detect cycles.
67+
The algorithm is easy to understand.
68+
First, we build the adjacent list and count all the inbound of the node.
69+
Then we start from the node whose inbound count is 0, adding it in to the `q_next`.
70+
For every node we pop out from q_next
71+
* We remove the node's outbound by decrease 1 on all its neighbor's inbound.
72+
* Put the node's neighbor to `q_next` if it has no inbound
73+
* Put the node into the `q`
74+
Repeat the process until there is no more node.
75+
The order in the `q` is the order we are going to encounter when we run through the directed graph.
76+
If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph.
8177
82-
78+
Time: O(E+2V) ~= O(E+V)
79+
we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3].
80+
Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`.
81+
"""

problems/find-mode-in-binary-search-tree.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def findMode(self, root):
6666
With the help of `prev_val` we can know that `curr_node` is the same to the previous or not.
6767
If not, its a new element, we need to reset the `curr_count`.
6868
69-
Time: O(N). Space: O(1)
69+
Time: O(N). Space: O(LogN)
7070
7171
For better understanding, below is a template for inorder traverse.
7272
"""

0 commit comments

Comments
 (0)