编程语言
首页 > 编程语言> > 算法--猜字谜(哈希表优化)

算法--猜字谜(哈希表优化)

作者:互联网

算法–猜字谜(哈希表优化)

元宵节的时候,力扣上的每日一题是这样的:

外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。 字谜的迷面 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’。
  • 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处*。

其中一种解法如下:哈希表特征码匹配法,子集使用深度优先搜索
(源代码没太仔细注释,本人试图注释一番,因为这位大佬的代码逻辑非常清楚,很适合他人学习。)
代码来源:力扣用户:verygoodlee
侵权必删


class Solution {
    public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
    	//创建哈希表
          Map<Integer, Integer> map = new HashMap<>();
        for (String word : words) {		//遍历words字符数组
            int key = 0;
    
            for (char ch : word.toCharArray())
            key |= 1 << ch - 'a';//把每个单词中每个字母ASCII码相加,再与1进行位或运算,生成独特的key值,|=按位或运算,<<左移ch-'a'位
            
            //把相应的单词所代表的key存放进hash表,value统一为1.           
            map.put(key, map.getOrDefault(key, 0) + 1);
        }
        List<Integer> res = new ArrayList<>(puzzles.length);
        for (String p : puzzles) {	//遍历puzzles字符数组
            char[] puzzle = p.toCharArray();
            res.add(dfs(puzzle, 1, map, 1 << puzzle[0] - 'a'));// 首字符必选
        }
        return res;
    }
    public int dfs(char[] puzzle, int idx, Map<Integer, Integer> map, int key) {
        if (idx == puzzle.length) return map.getOrDefault(key, 0);
        // 首字符之外的字符可选可不选,两种情况
        return dfs(puzzle, idx + 1, map, key) + dfs(puzzle, idx + 1, map, key | 1 << puzzle[idx] - 'a');
		//前者dfs递归完毕直接返回 map.getOrDefault(1 << puzzle[0] - 'a',0),如果map中包含puzzle[0]头字母的key,则返回1,表示一个单词可以作为谜底
		//后者dfs递归完puzzle中每一个字母,将puzzle中不重复出现的字母ASCII码值,获取了puzzle的key值,并使用map.getOrDefault(key,0),查找map中是否有相同的key,如果相同,返回value=1.
    }
}

总结:
1.压缩状态,将word(模式串)的哈希值算出,并存放入map,value为1.
2.匹配哈希值,其中首字母必定选取,

标签:map,谜底,哈希,--,puzzle,puzzles,单词,猜字谜,words
来源: https://blog.csdn.net/weixin_44270165/article/details/114161510