LeetCode676. Implement Magic Dictionary & 295. Find Median from Data Stream
阿新 • • 發佈:2019-01-07
LeetCode676. Implement Magic Dictionary & 295. Find Median from Data Stream
LeetCode-676. Implement Magic Dictionary
題目連結
題目
解析
兩種解法: 模糊搜尋和利用字典樹。
模糊搜尋:
buildDict
過程:
- 準備一個
HashMap<String, HashSet<Character>>
key
存字串,val
存的是字元的集合; - 其中
key
是在列舉每一個字串的每一個位置,去掉原來的那個字元,然後用一個特殊字元加入進去,並把替換的字元加入val
中的set
集合。
search
過程:
- 檢視在替換任意一個字元,之後的集合,且這個集合中不能包含替換的字元,或者可以包含但是
set.size() > 1
也行。
class MagicDictionary {
private HashMap<String, HashSet<Character>>magicMap;
/** Initialize your data structure here. */
public MagicDictionary() {
magicMap = new HashMap<>();
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
for(int i = 0; i < dict.length; i++){
for(int j = 0; j < dict[i].length(); j++){
String key = dict[i].substring(0, j) + "*" + dict[i].substring(j+1, dict[i].length());
HashSet<Character>valSet = magicMap.get(key);
if(valSet == null)
valSet = new HashSet<>();
valSet.add(dict[i].charAt(j));
magicMap.put(key, valSet);
}
}
}
/** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
public boolean search(String word) {
for(int i = 0; i < word.length(); i++){
String key = word.substring(0, i) + "*" + word.substring(i+1, word.length());
HashSet<Character>valSet = magicMap.get(key);
if(valSet == null)
continue;
// 只要有一個滿足這種情況就可以了 注意第二種情況,例如查詢 hello,之前map裡如果有hello, hallo (valSet.size() > 1)也是可以的
if(!valSet.contains(word.charAt(i)) || valSet.size() > 1)
return true;
}
return false;
}
}
字典樹寫法
字典樹基礎可以看這裡。
插入沒什麼好說的,建立字典樹即可,search
的過程要維護一個isOneDiff
變數。表示的是當前是否已經有一個不同了。然後dfs
即可。
class MagicDictionary {
private class Node{
public boolean end;
public Node[] nexts;
public Node() {
end = false;
this.nexts = new Node[26];
}
}
private class Trie{
private Node root;
public Trie() {
this.root = new Node();
}
public void insert(String word){
Node cur = root;
for(int i = 0; i < word.length(); i++){
int index = word.charAt(i) - 'a';
if(cur.nexts[index] == null)
cur.nexts[index] = new Node();
cur = cur.nexts[index];
}
cur.end = true;
}
}
private Trie trie;
public MagicDictionary() {
trie = new Trie();
}
public void buildDict(String[] dict) {
for(int i = 0; i < dict.length; i++)
trie.insert(dict[i]);
}
public boolean search(String word) {
return rec(trie.root, word, 0, false);
}
public boolean rec(Node node, String word, int i, boolean isOneDiff){
if(i == word.length() && node.end && isOneDiff)
return true;
else if(i == word.length())
return false;
int index = word.charAt(i) - 'a';
for(int k = 0; k < 26; k++){
if(node.nexts[k] == null)
continue;
if(k == index && !isOneDiff){
if(rec(node.nexts[k], word, i+1, false))
return true;
} else if(k == index && isOneDiff){
if(rec(node.nexts[k], word, i+1, true))
return true;
}else if(k != index && !isOneDiff){
if(rec(node.nexts[k], word, i+1, true))
return true;
}
// k!=index && isOneDiff shouldn't be consider
}
return false;
}
}
LeetCode-295. Find Median from Data Stream
題目連結
題目
解析
準備兩個堆: 一個最大堆(maxHeap
),一個最小堆minHeap
。
- 最大堆儲存較小元素的一半,最大堆儲存較大元素的一半;
- 新增元素後,始終要維持要麼兩個堆的元素相等,要麼左邊的堆(
maxHeap
)元素比右邊多一個; - 如果不是上面兩種情況,就要在新增元素之後維護;
findMedian
函式: 查詢時,如果兩個堆的元素個數相等就返回兩個堆頂的元素的和除以一半,否則返回maxHeap.peek()
;
看一個例子:
num | smaller(maxHeap) | bigger(minHeap) | median |
---|---|---|---|
5 | 5 | 5.0 | |
8 | 5 | 8 | 6.5 |
2 | [2、5] | 8 | 5 |
11 | [2、5] | [8、11] | 6.5 |
3 | [2、3、5] | [8、11] | 5 |
4 | [2、3、4、5] | [8、11] | 先調整 |
[2、3、4] | [5、8、11] | 4.5 | |
14 | [2、3、4] | [5、8、11、14] | 先調整 |
[2、3、4、5] | [8、11、14] | 5 |
class MedianFinder {
private PriorityQueue<Integer>maxHeap; // 第一個(更小的)是最大堆 (左邊的)
private PriorityQueue<Integer>minHeap; // 第二個(更大的)是最小堆 (右邊的)
public MedianFinder() {
maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
minHeap = new PriorityQueue<>(); // java預設是最小堆 (堆頂最小)
}
public void addNum(int num) {
if(maxHeap.isEmpty() || (!maxHeap.isEmpty() && num <= maxHeap.peek()))
maxHeap.add(num);
else
minHeap.add(num);
if(maxHeap.size() < minHeap.size())
maxHeap.add(minHeap.poll());
else if(maxHeap.size() - minHeap.size() == 2)
minHeap.add(maxHeap.poll());
}
public double findMedian() {
if(maxHeap.size() == minHeap.size())
return (maxHeap.peek() + minHeap.peek())/2.0;
else // minHeap.size() = maxHeap.size() + 1;
return maxHeap.peek();
}
}