Skip to content

Commit a9671e8

Browse files
committed
no message
1 parent 2191a53 commit a9671e8

7 files changed

+176
-19
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ I found it makes sense to solve similar problems together, so that we can recogn
3737
3. [What should I know from the CLRS 3rd edition book if my aim is to get into Google?](https://www.quora.com/What-should-I-know-from-the-CLRS-3rd-edition-book-if-my-aim-is-to-get-into-Google/answer/Jimmy-Saade)
3838

3939
## Data Structures and Algorithms for beginners
40-
If you are new or know nothing about data structures and algorithms, I recommend [this course](<https://classroom.udacity.com/courses/ud513>). This course is taught in Python and design to help you find job and do well in the interview.
40+
If you are new or know nothing about data structures and algorithms, I recommend [this course](<https://www.udacity.com/course/data-structures-and-algorithms-in-python--ud513>). This course is taught in Python and design to help you find job and do well in the interview.
4141

4242

4343
# System Design

problems/accounts-merge.py

Lines changed: 99 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
"""
2+
Treat each email as a node.
3+
Build an adjacency graph. [0]
4+
5+
For every account's data
6+
First, lets check if the first email is already merged. [1]
7+
If the first email is already merged to other groups, then other emails will be in another group as well.
8+
So don't need to check.
9+
10+
Second, do a DFS starting from the first email. Put all the connected nodes into visited. [2]
11+
And append the sorted(visited) to the ans with name. [3]
12+
13+
Let N be the total number of emails. M be the total number of final groups.
14+
Build the graph takes O(N).
15+
For each final groups, we make a DFS to all nodes, taking O(MN).
16+
Sort the group takes O((N/M)*Log(N/M)) -> O((N/M)*(logN-LogM))
17+
Time: O(MN)
18+
Space: O(N)
19+
"""
120
from collections import defaultdict
221

322
class Solution(object):
@@ -31,22 +50,85 @@ def accountsMerge(self, accounts):
3150

3251
return ans
3352

34-
"""
35-
Treat each email as a node.
36-
Build an adjacency graph. [0]
37-
38-
For every account's data
39-
First, lets check if the first email is already merged. [1]
40-
If the first email is already merged to other groups, then other emails will be in another group as well.
41-
So don't need to check.
4253

43-
Second, do a DFS starting from the first email. Put all the connected nodes into visited. [2]
44-
And append the sorted(visited) to the ans with name. [3]
54+
#Union Find
55+
class Solution(object):
56+
def accountsMerge(self, accounts):
57+
def find(x):
58+
p = parents[x]
59+
while p!=parents[p]:
60+
p = find(p)
61+
parents[x] = p
62+
return p
63+
64+
def union(x, y):
65+
p1, p2 = find(x), find(y)
66+
if p1==p2: return
67+
parents[p2] = p1
68+
69+
parents = {}
70+
mailToName = {}
71+
72+
for account in accounts:
73+
name = account[0]
74+
root = account[1]
75+
if root not in parents: parents[root] = root
76+
root = find(root)
77+
mailToName[root] = name
78+
79+
for i in xrange(2, len(account)):
80+
email = account[i]
81+
if email in parents:
82+
union(parents[email], root)
83+
root = find(root)
84+
parents[email] = root
85+
86+
rootToMails = collections.defaultdict(list)
87+
for email in parents:
88+
rootToMails[find(email)].append(email)
89+
90+
ans = []
91+
for root in rootToMails:
92+
name = mailToName[root]
93+
mails = rootToMails[root]
94+
ans.append([name]+sorted(mails))
95+
96+
return ans
4597

46-
Let N be the total number of emails. M be the total number of final groups.
47-
Build the graph takes O(N).
48-
For each final groups, we make a DFS to all nodes, taking O(MN).
49-
Sort the group takes O((N/M)*Log(N/M)) -> O((N/M)*(logN-LogM))
50-
Time: O(MN)
51-
Space: O(N)
52-
"""
98+
#DFS
99+
class Solution(object):
100+
def accountsMerge(self, accounts):
101+
102+
#build adjacency list
103+
adj = collections.defaultdict(list)
104+
for account in accounts:
105+
name = account[0]
106+
email0 = account[1]
107+
for i in xrange(2, len(account)):
108+
email = account[i]
109+
adj[email0].append(email)
110+
adj[email].append(email0)
111+
112+
#iterate accounts and dfs each email group
113+
ans = []
114+
visited = set() #store all the visited email
115+
for account in accounts:
116+
name = account[0]
117+
email0 = account[1]
118+
if email0 in visited: continue
119+
120+
#dfs
121+
group = set() #store the email group related to email0
122+
stack = [email0]
123+
while stack:
124+
email = stack.pop()
125+
if email in group or email in visited: continue
126+
group.add(email)
127+
visited.add(email)
128+
for nei in adj[email]:
129+
stack.append(nei)
130+
131+
ans.append([name]+sorted(list(group)))
132+
133+
return ans
134+

problems/diagonal-traverse.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Solution(object):
2+
def findDiagonalOrder(self, mat):
3+
def helper(i, j, reverse):
4+
output = []
5+
while 0<=i<len(mat) and 0<=j<len(mat[0]):
6+
output.append(mat[i][j])
7+
i += 1
8+
j -= 1
9+
return output if not reverse else reversed(output)
10+
11+
12+
M = len(mat)
13+
N = len(mat[0])
14+
ans = []
15+
reverse = True
16+
17+
for j in xrange(N):
18+
ans += helper(0, j, reverse)
19+
reverse = not reverse
20+
21+
for i in xrange(1, M):
22+
ans += helper(i, N-1, reverse)
23+
reverse = not reverse
24+
25+
return ans

problems/group-shifted-strings.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution(object):
2+
def groupStrings(self, strings):
3+
def getHash(string):
4+
h = ''
5+
offset = getNumByChar(string[0])*-1
6+
for c in string:
7+
h += getCharByNum((getNumByChar(c)+offset) if (getNumByChar(c)+offset)>=0 else 26+(getNumByChar(c)+offset))
8+
return h
9+
10+
def getNumByChar(letter):
11+
return ord(letter) - 97
12+
13+
def getCharByNum(pos):
14+
return chr(pos + 97)
15+
16+
groups = collections.defaultdict(list)
17+
for string in strings:
18+
h = getHash(string)
19+
groups[h].append(string)
20+
return groups.values()

problems/making-a-large-island.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
"""
2+
For each "island" asign them a group id. Also calculate the group's size.
3+
Iterate all the zeros, update the ans.
4+
5+
Time:O(MN)
6+
Space: O(MN) in the worst case.
7+
"""
18
class Solution(object):
29
def largestIsland(self, grid):
310
def isValid(i, j, M, N):

problems/maximum-swap.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
1. Generate positions. Storing the mapping between number to indices.
3+
2. Iterate from left, for each n1, find the largest number larger than n1 (searching from 9, 8, 7 to n1+1).
4+
3. Since we need to find the max output. There might be multiple the same number, we need to find the index of the rightest number.
5+
4. Remove n1 when it is done. Because right of the n1 should not consider it anymore.
6+
"""
7+
class Solution(object):
8+
def maximumSwap(self, num):
9+
numList = [int(n) for n in str(num)]
10+
positions = collections.defaultdict(list)
11+
for i, n in enumerate(numList): positions[n].append(i) #[1]
12+
13+
i = 0
14+
for i, n1 in enumerate(numList): #[2]
15+
n1 = numList[i]
16+
for n2 in xrange(9, n1, -1):
17+
if n2 in positions and len(positions[n2])>0:
18+
j = positions[n2][-1] #[3]
19+
numList[i], numList[j] = numList[j], numList[i]
20+
return int(''.join([str(n) for n in numList]))
21+
positions[n1].pop(0) #[4]
22+
23+
return num

problems/valid-number.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ def isOK(s, maxDots):
4141
elif eCount==1:
4242
return isOK(s[:ePos], 1) and isOK(s[ePos+1:], 0)
4343
else:
44-
return isOK(s, 1)
44+
return isOK(s, 1)

0 commit comments

Comments
 (0)