LeetCode解析------1178.猜字謎-位運算

題目:

外國友人仿照中國字謎設計了一個英文版猜字謎小遊戲,請你來猜猜看吧。

字謎的迷面 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;
    }
}

在這裏插入圖片描述

結語:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章