Skip to content

Commit e5d51b3

Browse files
authored
Create search-suggestions-system.py
1 parent fb3203a commit e5d51b3

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

Python/search-suggestions-system.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Time: ctor: O(n * l), n is the number of products
2+
# , l is the average length of product name
3+
# suggest: O(l^2)
4+
# Space: O(t), t is the number of nodes in trie
5+
6+
import collections
7+
8+
9+
class TrieNode(object):
10+
11+
def __init__(self):
12+
self.__TOP_COUNT = 3
13+
self.leaves = collections.defaultdict(TrieNode)
14+
self.infos = []
15+
16+
def insert(self, words, i):
17+
curr = self
18+
for c in words[i]:
19+
curr = curr.leaves[c]
20+
curr.add_info(words, i)
21+
22+
def add_info(self, words, i):
23+
self.infos.append(i)
24+
self.infos.sort(key=lambda x: words[x])
25+
if len(self.infos) > self.__TOP_COUNT:
26+
self.infos.pop()
27+
28+
29+
class Solution(object):
30+
def suggestedProducts(self, products, searchWord):
31+
"""
32+
:type products: List[str]
33+
:type searchWord: str
34+
:rtype: List[List[str]]
35+
"""
36+
trie = TrieNode()
37+
for i in xrange(len(products)):
38+
trie.insert(products, i)
39+
result = [[] for _ in xrange(len(searchWord))]
40+
for i, c in enumerate(searchWord):
41+
if c not in trie.leaves:
42+
break
43+
trie = trie.leaves[c]
44+
result[i] = map(lambda x: products[x], trie.infos)
45+
return result
46+
47+
48+
# Time: ctor: O(n * l * log(n * l)), n is the number of products
49+
# , l is the average length of product name
50+
# suggest: O(l^2)
51+
# Space: O(t), t is the number of nodes in trie
52+
class TrieNode2(object):
53+
54+
def __init__(self):
55+
self.__TOP_COUNT = 3
56+
self.leaves = collections.defaultdict(TrieNode2)
57+
self.infos = []
58+
59+
def insert(self, words, i):
60+
curr = self
61+
for c in words[i]:
62+
curr = curr.leaves[c]
63+
curr.add_info(i)
64+
65+
def add_info(self, i):
66+
if len(self.infos) == self.__TOP_COUNT:
67+
return
68+
self.infos.append(i)
69+
70+
71+
class Solution2(object):
72+
def suggestedProducts(self, products, searchWord):
73+
"""
74+
:type products: List[str]
75+
:type searchWord: str
76+
:rtype: List[List[str]]
77+
"""
78+
products.sort()
79+
trie = TrieNode2()
80+
for i in xrange(len(products)):
81+
trie.insert(products, i)
82+
result = [[] for _ in xrange(len(searchWord))]
83+
for i, c in enumerate(searchWord):
84+
if c not in trie.leaves:
85+
break
86+
trie = trie.leaves[c]
87+
result[i] = map(lambda x: products[x], trie.infos)
88+
return result
89+
90+
91+
# Time: ctor: O(n * l * log(n * l)), n is the number of products
92+
# , l is the average length of product name
93+
# suggest: O(l^2 * n)
94+
# Space: O(n * l)
95+
import bisect
96+
97+
98+
class Solution3(object):
99+
def suggestedProducts(self, products, searchWord):
100+
"""
101+
:type products: List[str]
102+
:type searchWord: str
103+
:rtype: List[List[str]]
104+
"""
105+
products.sort() # Time: O(n * l * log(n * l))
106+
result = []
107+
prefix = ""
108+
for i, c in enumerate(searchWord): # Time: O(l)
109+
prefix += c
110+
start = bisect.bisect_left(products, prefix) # Time: O(log(n * l))
111+
new_products = []
112+
for j in xrange(start, len(products)): # Time: O(n * l)
113+
if not (i < len(products[j]) and products[j][i] == c):
114+
break
115+
new_products.append(products[j])
116+
products = new_products
117+
result.append(products[:3])
118+
return result

0 commit comments

Comments
 (0)