題目:
外國友人仿照中國字謎設計了一個英文版猜字謎小遊戲,請你來猜猜看吧。
字謎的迷面 puzzle 按字符串形式給出,如果一個單詞 word 符合下面兩個條件,那麼它就可以算作謎底:
單詞 word 中包含謎面 puzzle 的第一個字母。
單詞 word 中的每一個字母都可以在謎面 puzzle 中找到。
例如,如果字謎的謎面是 “abcdefg”,那麼可以作爲謎底的單詞有 “faced”, “cabbage”, 和 “baggage”;而 “beefed”(不含字母 “a”)以及 “based”(其中的 “s” 沒有出現在謎面中)。
返回一個答案數組 answer,數組中的每個元素 answer[i] 是在給出的單詞列表 words 中可以作爲字謎迷面 puzzles[i] 所對應的謎底的單詞數目。
示例:
輸入:
words = [“aaaa”,“asas”,“able”,“ability”,“actt”,“actor”,“access”],
puzzles = [“aboveyz”,“abrodyz”,“abslute”,“absoryz”,“actresz”,“gaswxyz”]
輸出:
[1,1,3,2,4,0]
解釋:
1 個單詞可以作爲 “aboveyz” 的謎底 : “aaaa”
1 個單詞可以作爲 “abrodyz” 的謎底 : “aaaa”
3 個單詞可以作爲 “abslute” 的謎底 : “aaaa”, “asas”, “able”
2 個單詞可以作爲 “absoryz” 的謎底 : “aaaa”, “asas”
4 個單詞可以作爲 “actresz” 的謎底 : “aaaa”, “asas”, “actt”, “access”
沒有單詞可以作爲 “gaswxyz” 的謎底,因爲列表中的單詞都不含字母 ‘g’。
提示:
1 <= words.length <= 10^5
4 <= words[i].length <= 50
1 <= puzzles.length <= 10^4
puzzles[i].length == 7
words[i][j], puzzles[i][j] 都是小寫英文字母。
每個 puzzles[i] 所包含的字符都不重複。
簡單介紹:
題目:猜字謎
題目難度:困難
使用語言:JAVA。
這道題來自leetcode題庫的位運算標籤。
解題思路:
首先看題、分析題意,我們可以明確1個關鍵點:
1.如何去簡化計算量(遍歷的方式會超時)
既然,我們已經分析出來題目的關鍵任務了,下面我們就可以開始思考實現了。
我們採用算法與數據結構的思路來剖析一下這題,
數據結構:
要實現對數據的操作,我們要先明確存儲數據的數據結構。
該題的數據結構的作用:
1.動態列表res保存結果
2.哈希鍵值對統計單詞詞頻
算法:
既然明確了我們的數據結構,我們就可以開始我們的算法分析了。
1.統計words單詞的詞頻,用位運算將單詞轉化爲一個數。
2.搜索puzzles的模式子集,判斷首字母是否在word中出現,若出現,則將wordcount中的單詞詞頻(0或其他)添加爲該字謎的謎底數。
代碼部分:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Solution {
public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
List<Integer> res = new ArrayList<>(); //結果
HashMap<Integer, Integer> wordCount = new HashMap<>(); //單詞模式出現的次數。如aaa與aaaaa是同一類單詞模式
//統計同一單詞模式出現的次數
for (int i = 0; i < words.length; i++) {
int k = 0;
for (char c : words[i].toCharArray()) {
k |= (1 << (c - 'a')); //位運算 |:與運算,賦值各位 <<:移位也相當於乘2的n次方
}
wordCount.put(k, wordCount.getOrDefault(k, 0) + 1);//次數加1
}
//搜索模式子集
for (int i = 0; i < puzzles.length; i++) {
int k = 0;
for (char c : puzzles[i].toCharArray()) {
k |= (1 << (c - 'a')); //位運算 |:與運算,提取1 <<:移位也相當於乘2的n次方
}
int count=0;
for (int j=k;j>0;j=(j-1)&k){ //模式子集
if(((1<<(puzzles[i].charAt(0)-'a'))&j)>0){ //取位
count+=wordCount.getOrDefault(j,0);
}
}
res.add(count);
}
return res;
}
}
結語:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!