Skip to content

Commit 82cd50e

Browse files
committed
no message
1 parent 81ec8a5 commit 82cd50e

8 files changed

+282
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from sortedcontainers import SortedDict
2+
3+
class Node(object):
4+
def __init__(self, val):
5+
self.val = val
6+
self.key = None
7+
self.children = SortedDict()
8+
9+
10+
class Solution(object):
11+
def deleteDuplicateFolder(self, paths):
12+
def setKey(node):
13+
if not node.children:
14+
node.key = node.val
15+
else:
16+
node.key = ''
17+
for c in node.children:
18+
setKey(node.children[c])
19+
node.key += node.children[c].val + '|' + node.children[c].key + '|'
20+
21+
keyCount[node.key] += 1
22+
23+
def addPath(node, path):
24+
if node.children and keyCount[node.key]>1: return
25+
ans.append(path+[node.val])
26+
for c in node.children:
27+
addPath(node.children[c], path+[node.val])
28+
29+
30+
ans = []
31+
root = Node('/')
32+
keyCount = collections.Counter()
33+
34+
#build the tree
35+
for path in paths:
36+
node = root
37+
for c in path:
38+
if c not in node.children: node.children[c] = Node(c)
39+
node = node.children[c]
40+
41+
setKey(root)
42+
for c in root.children: addPath(root.children[c], [])
43+
return ans

problems/find-and-replace-in-string.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,32 @@ def findReplaceString(self, s, indices, sources, targets):
2020
ans += s[i]
2121
p = i
2222

23+
return ans
24+
25+
"""
26+
Time: O(N). N is the length of `s`. The replacement won't be more than the length of the string, Let's assume it is N.
27+
Space: O(N).
28+
"""
29+
class Solution(object):
30+
def findReplaceString(self, s, indices, sources, targets):
31+
ans = ''
32+
33+
replacement = {}
34+
for i in xrange(len(indices)):
35+
index = indices[i]
36+
source = sources[i]
37+
target = targets[i]
38+
39+
if s[index:index+len(source)]!=source: continue
40+
replacement[index] = (source, target)
41+
42+
i = 0
43+
while i<len(s):
44+
if i not in replacement:
45+
ans += s[i]
46+
i += 1
47+
else:
48+
ans += replacement[i][1]
49+
i += len(replacement[i][0])
50+
2351
return ans

problems/longest-string-chain.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,42 @@ def shortestPredecessor(word):
6666
return ans
6767

6868

69+
class Solution(object):
70+
def longestStrChain(self, words):
71+
def getLongestStringChain(word):
72+
if word in history: return history[word]
73+
if not orderedWords[len(word)+1]: return 1
74+
75+
temp = 0
76+
for word2 in orderedWords[len(word)+1]:
77+
if isPredecessor(word2, word):
78+
temp = max(temp, getLongestStringChain(word2))
79+
80+
history[word] = temp+1
81+
return temp+1
82+
83+
def isPredecessor(w2, w1):
84+
if len(w2)!=len(w1)+1: return False
85+
86+
j = 0
87+
for c in w1:
88+
found = False
89+
while j<len(w2):
90+
if c==w2[j]:
91+
found = True
92+
j += 1
93+
break
94+
else:
95+
j += 1
96+
if not found: return False
97+
98+
return True
99+
100+
orderedWords = collections.defaultdict(list)
101+
for word in words: orderedWords[len(word)].append(word)
102+
history = {}
103+
ans = 0
104+
105+
for word in words:
106+
ans = max(ans, getLongestStringChain(word))
107+
return ans
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
Time: O(NLogN), N is the number of points.
3+
Space: O(N)
4+
5+
1. Get the angle of each point relative to the "location"
6+
2. Sort the angles
7+
3. Do a sliding window to angles to see what the maximum number of angles within the interval "angle"
8+
9+
[1] For example, angles = [10, 20, 360], angle = 20 we will count 2, but actually it will be 3.
10+
"""
11+
class Solution(object):
12+
def visiblePoints(self, points, angle, location):
13+
def getAngle(x, y):
14+
#4 axis
15+
if x>0 and y==0:
16+
return 0
17+
elif x==0 and y>0:
18+
return 90
19+
elif x<0 and y==0:
20+
return 180
21+
elif x==0 and y<0:
22+
return 270
23+
24+
#4 quadrant
25+
if x>0 and y>0:
26+
return math.degrees(math.atan2(abs(y), abs(x)))
27+
elif x<0 and y>0:
28+
return 180-math.degrees(math.atan2(abs(y), abs(x)))
29+
elif x<0 and y<0:
30+
return 180+math.degrees(math.atan2(abs(y), abs(x)))
31+
else:
32+
return 360-math.degrees(math.atan2(abs(y), abs(x)))
33+
34+
ans = 0
35+
onLocation = 0
36+
angles = []
37+
38+
for x, y in points:
39+
if x==location[0] and y==location[1]:
40+
onLocation += 1
41+
else:
42+
a = getAngle(x-location[0], y-location[1])
43+
angles.append(a)
44+
if a<=angle: angles.append(360+a) #[1]
45+
46+
angles.sort()
47+
48+
i = 0
49+
for j in xrange(len(angles)):
50+
while angles[j]-angles[i]>angle:
51+
i += 1
52+
ans = max(ans, j-i+1)
53+
54+
return ans+onLocation
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
Time: O(WL x LogS), W is the length of words, L is the length of word.
3+
LogS is the time for binary search and S should be the count of repetitive words, we can assume it is Log(S/26) ~= LogS.
4+
5+
Space: O(S)
6+
"""
7+
class Solution(object):
8+
def numMatchingSubseq(self, s, words):
9+
def match(position, word):
10+
prev = -1
11+
for c in word:
12+
if c not in position: return False
13+
i = bisect.bisect_left(position[c], prev+1)
14+
if i==len(position[c]): return False
15+
prev = position[c][i]
16+
return True
17+
18+
position = collections.defaultdict(list)
19+
count = 0
20+
for i, c in enumerate(s):
21+
position[c].append(i)
22+
23+
for word in words:
24+
if match(position, word): count += 1
25+
return count
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
Not sure how to scientifically prove this.
3+
In order to turn all the 1 to 0, every row need to have "the same pattern". Or it is imposible.
4+
This same pattern is means they are 1. identical 2. entirely different.
5+
For example 101 and 101, 101 and 010.
6+
110011 and 110011. 110011 and 001100.
7+
8+
Time: O(N), N is the number of element in the grid.
9+
Space: O(N)
10+
"""
11+
class Solution(object):
12+
def removeOnes(self, grid):
13+
if not grid: return True
14+
rowStrings = set()
15+
16+
for row in grid:
17+
rowStrings.add(''.join((str(e) for e in row)))
18+
19+
if len(rowStrings)>2: return False
20+
if len(rowStrings)==1: return True
21+
22+
s1 = rowStrings.pop()
23+
s2 = rowStrings.pop()
24+
25+
for i in xrange(len(s1)):
26+
if (s1[i]=='0' and s2[i]=='1') or (s1[i]=='1' and s2[i]=='0'): continue
27+
return False
28+
return True

problems/stock-price-fluctuation.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
[0] priceToTime tracks price to timestamps, but since for each timestamp the price might be overridden, the price in priceToTime might not be exsit. So we need to check if the price still have any valid timestamps.
3+
[1] SortedDict is a BST like structure.
4+
5+
Time: O(LogN)
6+
Space: O(N)
7+
"""
8+
from sortedcontainers import SortedDict #[1]
9+
10+
class StockPrice(object):
11+
12+
def __init__(self):
13+
self.timeToPrice = SortedDict() #time will be sorted
14+
self.priceToTime = SortedDict() #the price will be sorted
15+
16+
17+
def update(self, timestamp, price):
18+
if timestamp in self.timeToPrice:
19+
prevPrice = self.timeToPrice[timestamp]
20+
self.priceToTime[prevPrice].remove(timestamp)
21+
if len(self.priceToTime[prevPrice])==0: self.priceToTime.pop(prevPrice) #[0]
22+
23+
if price not in self.priceToTime: self.priceToTime[price] = set() #initialized
24+
self.priceToTime[price].add(timestamp)
25+
self.timeToPrice[timestamp] = price
26+
27+
28+
def current(self):
29+
return self.timeToPrice.peekitem(-1)[1]
30+
31+
32+
def maximum(self):
33+
return self.priceToTime.peekitem(-1)[0]
34+
35+
36+
def minimum(self):
37+
return self.priceToTime.peekitem(0)[0]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class Solution(object):
2+
def checkRecord(self, n):
3+
"""
4+
dp[l] := number of eligible combination of a length l record without A
5+
"""
6+
7+
ans = 0
8+
M = 1000000007
9+
10+
dp = [0]*max(n+1, 4)
11+
dp[0] = 1
12+
dp[1] = 2
13+
dp[2] = 4
14+
dp[3] = 7
15+
16+
for i in xrange(4, n+1):
17+
dp[i] += dp[i-1]%M #ends at P
18+
dp[i] += (dp[i-1]%M - dp[i-4]%M) #ends at L. All posiblity but the end cannot be PLL
19+
20+
21+
ans += dp[n]
22+
23+
for i in xrange(n):
24+
ans += dp[i] * dp[n-i-1]
25+
ans %= M
26+
27+
return ans
28+

0 commit comments

Comments
 (0)