Skip to content

Commit f710b64

Browse files
committed
update
1 parent 7fb31d9 commit f710b64

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3759
-2759
lines changed
File renamed without changes.
File renamed without changes.

Java/Convert Binary Search Tree to Sorted Doubly Linked List.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
M
2-
1531694102
3-
tags: Linked List, Tree, DFS, BST
2+
1533494672
3+
tags: Linked List, Tree, DFS, BST, Divide and Conquer
44
time: O(n)
55
space: O(1)
66

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
H
2+
1533426244
3+
tags: Design, Trie, Hash Table, MinHeap, PriorityQueue
4+
time: input: O(x), where x = possible words, constructor: O(mn) m = max length, n = # of words
5+
space: O(n^2), n = # of possible words, n = # of trie levels; mainlay saving the `Map<S, freq>`
6+
7+
Description is long, but in short: search auto complete.
8+
9+
Best problem to review Trie (prefix search), Top K frequent elements (Hash Map), and MinHeap (PriorityQueue)
10+
11+
Easier to revisit https://leetcode.com/problems/design-search-autocomplete-system/description/
12+
13+
#### 思考方向
14+
- 做text的search, 毋庸置疑要用Prefix tree, trie.
15+
16+
##### Find all possible word/leaf, 两种方案:
17+
- Trie造好之后, 做prefix search, 然后DFS/BFS return all leaf items. [high runtime complexity]
18+
- 在TrieNode里面存所有的possible words. [high space usage]
19+
- in memory space 应该不是大问题, 所以我们可以选择 store all possible words
20+
21+
##### Given k words, find top k frequent items. 肯定用MinHeap, 但也有两种方案:
22+
- Store MinHeap with TrieNode: 因为会不断搜索新此条, 同样的prefix (尤其是在higher level), 会被多次搜索.
23+
- [complexity: need to update heaps across all visited TrieNodes once new sentence is completed]
24+
- Compute MinHeap on the fly: 当然我们不能每次都来一个DFS不然会很慢, 所以就必须要store list of possible candidates in TrieNode.
25+
- 这里就用到了`Top K Frequent Words` 里面的 `Map<String, freq>`, 这样O(m) 构建 min-heap其实很方便.
26+
27+
##### Train the system
28+
- 每次 `#` 标记一个词条被add进search history. 那么就要 `insert it into trie`.
29+
- 这一条在最后遇到`#`再做就可以了, 非常简洁
30+
31+
#### Trie, PriorityQueue, HashMap
32+
- Trie Prefix Search + maintain top k frequent items
33+
-
34+
35+
```
36+
/*
37+
LeetCode.
38+
https://leetcode.com/problems/design-search-autocomplete-system/description/
39+
40+
Design a search autocomplete system for a search engine.
41+
Users may input a sentence (at least one word and end with a special character '#').
42+
For each character they type except '#', you need to return the top 3 historical hot sentences
43+
that have prefix the same as the part of sentence already typed.
44+
45+
Here are the specific rules:
46+
47+
The hot degree for a sentence is defined as the number of times a user typed the exactly same sentence before.
48+
49+
The returned top 3 hot sentences should be sorted by hot degree (The first is the hottest one).
50+
If several sentences have the same degree of hot, you need to use ASCII-code order (smaller one appears first).
51+
52+
If less than 3 hot sentences exist, then just return as many as you can.
53+
54+
When the input is a special character, it means the sentence ends, and in this case, you need to return an empty list.
55+
56+
Your job is to implement the following functions:
57+
58+
The constructor function:
59+
60+
- AutocompleteSystem(String[] sentences, int[] times): This is the constructor.
61+
The input is historical data. Sentences is a string array consists of previously typed sentences.
62+
Times is the corresponding times a sentence has been typed. Your system should record these historical data.
63+
64+
- Now, the user wants to input a new sentence. The following function will provide the next character the user types:
65+
66+
List<String> input(char c): The input c is the next character typed by the user.
67+
The character will only be lower-case letters ('a' to 'z'), blank space (' ') or a special character ('#').
68+
Also, the previously typed sentence should be recorded in your system.
69+
The output will be the top 3 historical hot sentences that have prefix the same as the part of sentence already typed.
70+
71+
72+
Example:
73+
Operation: AutocompleteSystem(["i love you", "island","ironman", "i love leetcode"], [5,3,2,2])
74+
The system have already tracked down the following sentences and their corresponding times:
75+
"i love you" : 5 times
76+
"island" : 3 times
77+
"ironman" : 2 times
78+
"i love leetcode" : 2 times
79+
Now, the user begins another search:
80+
81+
Operation: input('i')
82+
Output: ["i love you", "island","i love leetcode"]
83+
Explanation:
84+
There are four sentences that have prefix "i". Among them, "ironman" and "i love leetcode" have same hot degree.
85+
Since ' ' has ASCII code 32 and 'r' has ASCII code 114, "i love leetcode" should be in front of "ironman".
86+
Also we only need to output top 3 hot sentences, so "ironman" will be ignored.
87+
88+
Operation: input(' ')
89+
Output: ["i love you","i love leetcode"]
90+
Explanation:
91+
There are only two sentences that have prefix "i ".
92+
93+
Operation: input('a')
94+
Output: []
95+
Explanation:
96+
There are no sentences that have prefix "i a".
97+
98+
Operation: input('#')
99+
Output: []
100+
Explanation:
101+
The user finished the input, the sentence "i a" should be saved as a historical sentence in system.
102+
And the following input will be counted as a new search.
103+
104+
Note:
105+
The input sentence will always start with a letter and end with '#', and only one blank space will exist between two words.
106+
The number of complete sentences that to be searched won't exceed 100. The length of each sentence including those in the historical data won't exceed 100.
107+
Please use double-quote instead of single-quote when you write test cases even for a character input.
108+
Please remember to RESET your class variables declared in class AutocompleteSystem, as static/class variables are persisted across multiple test cases. Please see here for more details.
109+
*/
110+
111+
class AutocompleteSystem {
112+
class TrieNode {
113+
public boolean isEnd;
114+
public Map<String, Integer> freq;
115+
public Map<Character, TrieNode> children; // Map is more applicable to all chars, not limited to 256 ASCII
116+
public TrieNode() {
117+
this.freq = new HashMap<>();
118+
this.children = new HashMap<>();
119+
}
120+
}
121+
class Pair {
122+
String s;
123+
int count;
124+
public Pair(String s, int count) {
125+
this.s = s;
126+
this.count = count;
127+
}
128+
}
129+
TrieNode root, curr;
130+
StringBuffer sb;
131+
public AutocompleteSystem(String[] sentences, int[] times) {
132+
if (sentences == null || times == null || sentences.length != times.length) return;
133+
reset();
134+
root = new TrieNode();
135+
for (int i = 0; i < times.length; i++) {
136+
insert(sentences[i], times[i]);
137+
}
138+
}
139+
140+
public List<String> input(char c) {
141+
List<String> rst = new ArrayList<>();
142+
if (curr == null) curr = root;
143+
if (c == '#') { // save sentence and reset state
144+
insert(sb.toString(), 1);
145+
reset();
146+
return rst;
147+
}
148+
149+
// Update global variable (curr TrieNode and string buffer); or append new character if not exist.
150+
sb.append(c);
151+
curr.children.putIfAbsent(c, new TrieNode());
152+
curr = curr.children.get(c);
153+
154+
// MinHeap to find top 3.
155+
rst.addAll(findTopK(curr, 3));
156+
157+
return rst;
158+
}
159+
160+
private List<String> findTopK(TrieNode node, int k) {
161+
List<String> rst = new ArrayList<>();
162+
if (node.freq.isEmpty()) return rst;
163+
PriorityQueue<Pair> queue = new PriorityQueue<>(
164+
(a, b) -> a.count == b.count ? b.s.compareTo(a.s) : a.count - b.count);
165+
for (Map.Entry<String, Integer> entry : node.freq.entrySet()) {
166+
if (queue.size() < 3 || entry.getValue() >= queue.peek().count) {
167+
queue.offer(new Pair(entry.getKey(), entry.getValue()));
168+
}
169+
if (queue.size() > 3) queue.poll();
170+
}
171+
172+
while (!queue.isEmpty()) {
173+
rst.add(0, queue.poll().s);
174+
}
175+
176+
return rst;
177+
}
178+
179+
private void reset() {
180+
curr = null;
181+
sb = new StringBuffer();
182+
}
183+
184+
private void insert(String sentence, int count) {
185+
if (sentence == null || sentence.length() == 0) return;
186+
TrieNode node = root;
187+
for (char c : sentence.toCharArray()) {
188+
node.children.putIfAbsent(c, new TrieNode());
189+
node = node.children.get(c);
190+
node.freq.put(sentence, node.freq.getOrDefault(sentence, 0) + count);
191+
}
192+
node.isEnd = true; // can set word to node as well, if needed
193+
}
194+
}
195+
196+
/**
197+
* Your AutocompleteSystem object will be instantiated and called as such:
198+
* AutocompleteSystem obj = new AutocompleteSystem(sentences, times);
199+
* List<String> param_1 = obj.input(c);
200+
*/
201+
202+
```
File renamed without changes.

Java/Prefix and Suffix Search.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
H
2+
tags: Trie
3+
4+
```
5+
/*
6+
Given many words, words[i] has weight i.
7+
8+
Design a class WordFilter that supports one function,
9+
WordFilter.f(String prefix, String suffix).
10+
It will return the word with given prefix and suffix with maximum weight. If no word exists, return -1.
11+
12+
Examples:
13+
Input:
14+
WordFilter(["apple"])
15+
WordFilter.f("a", "e") // returns 0
16+
WordFilter.f("b", "") // returns -1
17+
Note:
18+
words has length in range [1, 15000].
19+
For each test case, up to words.length queries WordFilter.f may be made.
20+
words[i] has length in range [1, 10].
21+
prefix, suffix have lengths in range [0, 10].
22+
words[i] and prefix, suffix queries consist of lowercase letters only.
23+
24+
25+
*/
26+
27+
/*
28+
Thought1:
29+
TrieNode {
30+
boolean isEnd; int weight;
31+
32+
// suffix use as validation for suffix search, built based on [prefixIndex+1, end].
33+
// This will requires lots of in-memory space to save all possible suffix: [e, le, ple, pple] all map to apple
34+
HashMap<Suffix, List<weight/index>> suffix map;
35+
Map<c, TrieNode> children
36+
}
37+
Functions:
38+
insert(); // build trie
39+
generateSubStrings(int i): set<string>
40+
f: search using prefix, find the TrieNode where prefix lands; use suffix to find list of weights. Return max.
41+
search time: O(n) to find max
42+
*/
43+
44+
/*
45+
Thought2:
46+
Build 2 trie structure: regular order, and reverse order.
47+
search: find set1, find set2;
48+
intersect to return max.
49+
search time: O(n) compare, O(n) find max
50+
*/
51+
```

0 commit comments

Comments
 (0)