LeetCode1178日の1つの質問。ワードパズル

1178.ワードパズル

外国人の友達が中国語の単語パズルをベースにした英語版の単語推測ゲームをデザインしました。ぜひ推測してみてください。

パズルファンは、次の2つの条件がpuzzleあればword単語が与えられた文字列に直面し、それが答えとして数えられます。

  • 単語wordにはpuzzle最初の文字のなぞなぞ含まれています
  • wordなぞなぞの各文字の単語puzzleにあります。

たとえば、パズルのなぞなぞがである場合、"abcdefg"答えの単語"faced""cabbage"あり"baggage"、; while "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]文字には繰り返しが含まれていません。

方法1:状態の圧縮+列挙

問題解決のアイデア

この問題に対する暴力的な解決策を想像するのは難しいことではありません各謎puzzlewords解決するためにトラバース行きます。
ヒントによると、パズルの顔10^4の最大値、パズルの最大値は、10^5一緒10^9乗算すると、間違いなくタイムアウトになります。

したがって、他の解決策を検討する必要があります。

  • ヒントによると、パズルの顔と答えの両方に小文字しか含まれておらず、繰り返される文字は気にしません。なぞなぞや謎については、文字があったかどうかだけを気にするので、26ビットbit文字列化して、左から右に、それぞれ値0の文字za表示されないことを示し、1が表示されることを表すことができます。
  • JavaのIntには32ビットがあり、intの最後の26ビットを直接使用して文字列を表すことができます。

上記の圧縮プロセスを理解した後、特定の実装手順を見てみましょう。

  • まず、回答wordsデジタル、異なる文字列にはword、このような同じ番号、になるかもしれない“ab”し、“aaabbb”デジタルすべてに3したがって、各番号の頻度を数えるためにマップが必要です。
  • パズルの表面puzzlesトラバースし、同じ方法でパズルの表面を数字に変えます。ヒントによると、パズルの顔には7ビットしかありません。つまり、変換された数値の2進ビットには7ビットしかありません。我々ができ列挙するすべてのサブセット(2 7であれば、どのようなサブセットとしてのために、 - 1)最初の文字が含まれており、存在がマップに有効です。

詳細:

  • subnum = (subnum - 1) & bitnumbitnumすべてのサブセットを列挙するために、このコード描画を理解するようにしてください。

参照コード

public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
    
    
	// 把 words 中的字符串转为数字,并统计数字的出现次数。
    Map<Integer, Integer> freq = new HashMap<>();
    for (String word : words) {
    
    
        int bitnum = getBitnum(word);
        freq.put(bitnum, freq.getOrDefault(bitnum, 0) + 1);
    }
	
    List<Integer> ans = new ArrayList<>();
    for (String puzzle : puzzles) {
    
    
        int bitnum = getBitnum(puzzle);
        int first = 1 << (puzzle.charAt(0) - 'a');
        int subnum = bitnum;
        int count = 0;
        // 枚举谜面的所有子集:包含首字母 && map中存在
        while (subnum > 0) {
    
    
            if ((subnum & first) > 0 && freq.containsKey(subnum)) {
    
    
                count += freq.get(subnum);
            }
            subnum = (subnum - 1) & bitnum;
        }
        ans.add(count);
    }
    return ans;
}
public Integer getBitnum(String s) {
    
    
    int bitnum = 0;
    for (char ch : s.toCharArray()) {
    
    
        bitnum |= (1 << (ch - 'a'));
    }
    return bitnum;
}

の結果
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_27007509/article/details/114125796