记录一下leetcode:1178猜字谜
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** leetcode: 1178.猜字谜* <p>* 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。* <p>* 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底:* <p>* 单词 word 中包含谜面 puzzle 的第一个字母。* 单词 word 中的每一个字母都可以在谜面 puzzle 中找到。* 例如,如果字谜的谜面是 "abcdefg",那么可以作为谜底的单词有 "faced", "cabbage", 和 "baggage";而 "beefed"(不含字母 "a")以及 "based"(其中的 "s" 没有出现在谜面中)。* 返回一个答案数组 answer,数组中的每个元素 answer[i] 是在给出的单词列表 words 中可以作为字谜迷面 puzzles[i] 所对应的谜底的单词数目。* <p>* 输入:* 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'。** @Author: xiaofeifei* @Date: 2021/2/26 10:49*/
public class FindNumOfValidWords {public static void main(String[] args) {// System.out.println(findNumOfValidWords(new String[]{"aaaa", "asas", "able", "ability", "actt", "actor", "access"}, new String[]{"aboveyz", "abrodyz", "abslute", "absoryz", "actresz", "gaswxyz"}));System.out.println(findNumOfValidWords1(new String[]{"aaaa", "asas", "able", "ability", "actt", "actor", "access"}, new String[]{"aboveyz", "abrodyz", "abslute", "absoryz", "actresz", "gaswxyz"}));}public static boolean contains(String puzzle, Set<String> set) {// 1. word 中的字母必须包含puzzle的首字母if (!set.contains(String.valueOf(puzzle.charAt(0)))) {return false;}// 2. word 中的每个字母必须在puzzle中有所包含for (String s : set) {if (!puzzle.contains(s)) {return false;}}return true;}/*** 思路:* 1. word 中的字母必须包含puzzle的首字母* 2. word 中的每个字母必须在puzzle中有所包含* 3. puzzles[i].length == 7 => 表示puzzle的长度固定为7* 4. 每个 puzzles[i] 所包含的字符都不重复* <p>* 对word进行字母去重 然后相互比较* <p>* <p>* 这种方法可以实现 但是不能满足leetcode自身的执行时间限制** @param words* @param puzzles* @return*/public static List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {int[] result = new int[puzzles.length];int puzzleLen = puzzles.length;List<String> puzzleCharList = Stream.of(puzzles).map(puzzle -> String.valueOf(puzzle.charAt(0))).collect(Collectors.toList());List<Set<String>> wordList = Stream.of(words).filter(word -> {for (String puzzleFirst : puzzleCharList) {if (word.contains(puzzleFirst)) {return true;}}return false;}).map(word -> {char[] charArr = word.toCharArray();// 校验是否满足第一个条件// 去重处理Set<String> set = new HashSet<>(charArr.length);for (char ch : charArr) {set.add(String.valueOf(ch));}return set;}).collect(Collectors.toList());// 对puzzles进行排序for (int p = 0; p < puzzleLen; p++) {for (Set<String> strings : wordList) {if (contains(puzzles[p], strings)) {result[p]++;}}}ArrayList<Integer> nums = new ArrayList<>(puzzles.length);for (int num : result) {nums.add(num);}return nums;}/*** leetcode 官方解答:* <p>* 因为都是小写字母 所以可以用0 -> 25位来表示 a -> z* <p>* a => 97 所以将字符转为整型 再减去a则得到具体的值 然后转换成二进制** @param words* @param puzzles* @return*/public static List<Integer> findNumOfValidWords1(String[] words, String[] puzzles) {// 用来记录words的表示集合 方便后续存取List<Integer> result = new ArrayList<>(puzzles.length);Map<Integer, Integer> frequency = new HashMap<>();for (String word : words) {// mask用来表示word的二进制表示形式比如说abcdefg => 0111 1111int mask = 0;for (int i = 0; i < word.length(); i++) {char ch = word.charAt(i);// 比如说ch为c=3 1 << 3 => 0000 1000// 这样即使字符出现重复 二进制的方式也完美解决了重复问题mask |= 1 << (ch - 'a');}// 获取二进制中1的数量 如果数量大于7 则它一定不会成为谜底 因为谜面本身就只有7位if (Integer.bitCount(mask) <= 7) {// 这里很关键哈,key用来记录word的二进制表示,value用来记录word的出现次数// 也就是是否重复了,相同的word则value就+1frequency.put(mask, frequency.getOrDefault(mask, 0) + 1);}}// 同理 将puzzles 也转换成二进制表示信息 肯定是7个1 puzzles本身// 然后再遍历中直接比较for (String puzzle : puzzles) {// 记录当前谜面匹配次数int total = 0;int mask = 0;// 这里请注意,这里获取到的mask是6位 不包含最高位// 因为最高位就是第一个字符,这里获取的是后6位的值// 一般认为应该是遍历7次 这里只使用6次循环的好处是 降低了执行时间成本for (int i = 1; i < puzzle.length(); i++) {mask |= (1 << (puzzle.charAt(i) - 'a'));}// 6个1 的puzzle 不包含最高位int subset = mask;do {// firstBit 用于表示puzzle的首字母int firstBit = 1 << (puzzle.charAt(0) - 'a');// 获取最后真实的puzzle的二进制int s = subset | firstBit;if (frequency.containsKey(s)) {total += frequency.get(s);}// 这里是核心// 比如说 puzzle 为 0111 1111// 因为最高位必须要满足 所以只需要比较6位为 0011 1111// 所以6为的子集为 2^7 - 1 & mask(0011 1111) -> 不包含 -1 & mask(0011 1111)这么多种可能// 然后加上首字母 组成二进制 判断frequency是否包含 包含则匹配成功 返回// 不包含则继续获取子集 直到获取的subset 为 0 即(subset - 1) = -1// -1 & mask = mask 所以当subset == mask时// 则应该跳出循环 至此 所以子集匹配结束// 这里的思想很聪明 跳过了 puzzles * words的遍历导致时间复杂度{O{M*N}}过大的问题// 而是转而利用二进制的本身机制 反向通过puzzle的二进制表示形式来反推其所有满足的子集是否存在于// words所表示的hashMap中,hashMap本身的散列机制,检索效率很快。// 因此它的时间复杂度要远远小于直接遍历判断的问题// (subset - 1) & mask 保证了其结果肯定为mask的子集 结果为负则子集遍历结束subset = (subset - 1) & mask;// 所以当subset == mask时会退出// 这里为什么不判断subset > 0 就好了呢,因此存在首字母// 因为subset是6个1 ,还有一个首字母 如果word就只包含首字母呢 则当subset为0时// 也是可以满足条件的,只有当subset = -1时才应该跳出循环} while (subset != mask);result.add(total);}return result;}
}
记录一下leetcode:1178猜字谜相关推荐
- leetcode 1178.猜字谜
leetcode 1178.猜字谜 题干 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么 ...
- leetcode 1178. 猜字谜(位运算)
外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底: 单词 word 中包含 ...
- LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)
文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...
- 【力扣】1178. 猜字谜
以下为力扣官方题解 1178. 猜字谜 题目 示例 提示 官方题解 前言 方法一 二进制状态压缩 思路与算法 细节 代码 复杂度分析 方法二:字典树 思路与算法 细节 代码 复杂度分析 题目 外国友人 ...
- leetcode 1178. Number of Valid Words for Each Puzzle | 1178. 猜字谜(bitmask位运算)
题目 https://leetcode.com/problems/number-of-valid-words-for-each-puzzle/ 题解 看了答案,堪称力扣最详细的答案,从时间复杂度的角度 ...
- 猜字谜 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底:
今天是元宵节,力扣也细心地为我们准备了一道有关节日的题,一起看看吧: 1178. 猜字谜 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出 ...
- Leetcode 猜字谜
WechatIMG521.jpeg 题目描述 leetcode 第1178题:猜字谜 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如 ...
- LeetCode日记_007_猜字谜
题目信息: 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面puzzle 按字符串形式给出,如果一个单词word符合下面两个条件,那么它就可以算作谜底: 单词word中包 ...
- 算法--猜字谜(哈希表优化)
算法–猜字谜(哈希表优化) 元宵节的时候,力扣上的每日一题是这样的: 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 wo ...
最新文章
- 经典不过时,回顾DeepCompression神经网络压缩
- JSON 数据格式解析(转)
- python3下载慢-PIP 下载慢,给你Python3的pip换个源 一键换源
- BOOST_PREDEF_WORKAROUND宏相关的测试程序
- 川大计算机高考分数,2020年四川大学录取分数是多少 2020年高考多少分可以报考四川大学...
- 解决import tensorflow时的报错 Passing (type, 1) or ‘1type‘ as a synonym of type is deprecate
- PKU 学生反馈 3
- MFC设置对话框背景色及控件颜色
- mysql 表死锁_MySQL Innodb表导致死锁日志情况分析与归纳
- SpringData环境搭建代码编写
- 小程序毕设作品之微信小程序点餐系统毕业设计(5)任务书
- 如何快速实现一个抽签小程序
- 介绍一款通过软件设置调节显示器亮度的工具:护眼宝
- 选择什么语言真的重要吗
- PS获取图片三种方式
- 微信小程序 家校通 中小学家校联系电子作业系统
- MQTT连接阿里云物联网平台步骤
- int类型以及指针的类型所占字节的大小,到底是由什么决定的?
- 如何在 Linux 服务器上安装 Red5?
- 十四年磨一剑,万能数据库查询分析器7.024版本 发布