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] 所包含的字符都不重复。

题解

直接模拟,用数组映射26个字母的出现次数,显然超时了

class Solution {public:vector<int> findNumOfValidWords(vector<string>& words, vector<string>& puzzles) {int puzzleCount = puzzles.size();int wordCount = words.size();vector<vector<int> > puzzleStat(puzzleCount,vector<int>(26,0));vector<vector<int> > wordStat(wordCount,vector<int>(26,0));vector<int> ans(puzzleCount); for(int i = 0 ; i < puzzleCount ; ++i){for(auto j : puzzles[i]){puzzleStat[i][j - 'a']++;}}for(int i = 0 ; i < wordCount ; ++i){for(auto j : words[i]){wordStat[i][j - 'a']++;}}for(int i = 0 ; i < puzzleCount ; ++i){int ansCount = 0;for(int j = 0 ; j < wordCount ; ++j){//如果j标words中有谜面的首字母if(wordStat[j][puzzles[i][0] - 'a'] != 0){bool flag = true;for(int k = 0 ; k < 26 ; ++k){//如果j标words中存在的字母在谜面中bu存在if(wordStat[j][k] != 0 && puzzleStat[i][k] == 0){flag = false;break;}}if(flag){ansCount++;}}}ans[i] = ansCount;}return ans;}
};

思考一下位运算的可能性,2^26 = 67108864 < INT_MAX
那好办,就不用数组映射字母出现次数了,用一个二进制int来映射就行,因为题目要求的判别并不用判断字母的个数,只要能够表示是否存在就可以了
还就那个继续超时

class Solution {public://获取num从右往左第n位int getDigit(int num,int n){num >>= n;return num & 1;}vector<int> findNumOfValidWords(vector<string>& words, vector<string>& puzzles) {int puzzleCount = puzzles.size();int wordCount = words.size();vector<int> puzzleStat(puzzleCount,0);vector<int> wordStat(wordCount,0);vector<int> ans(puzzleCount); for(int i = 0 ; i < puzzleCount ; ++i){int tempCount = 0;for(auto j : puzzles[i]){puzzleStat[i] |= 1 << (j - 'a');}}for(int i = 0 ; i < wordCount ; ++i){for(auto j : words[i]){wordStat[i] |= 1 << (j - 'a');}}for(int i = 0 ; i < puzzleCount ; ++i){int ansCount = 0;for(int j = 0 ; j < wordCount ; ++j){//如果j标words中有谜面的首字母//out<<getDigit(wordStat[j],puzzles[i][0] - 'a')<<endl;if(getDigit(wordStat[j],puzzles[i][0] - 'a') != 0){//如果words中存在的字母谜面中不存在//cout<<wordStat[j]<<' '<<puzzleStat[i]<<' '<<(wordStat[j] & puzzleStat[i])<<endl;if((wordStat[j] & puzzleStat[i]) == wordStat[j]){ansCount++;}}}ans[i] = ansCount;}return ans;}
};

那就只能反过来遍历了,根据谜面枚举谜面的所有二进制子集(因为谜面只有7位),然后把words对应的二进制信息放到哈希表中,通过谜面二进制的子集元素来检查哈希表

class Solution {public:vector<int> findNumOfValidWords(vector<string>& words, vector<string>& puzzles) {int puzzleCount = puzzles.size();int wordCount = words.size();unordered_map<int,int> wordsMask;vector<int> ans(puzzleCount,0); for(int i = 0 ; i < wordCount ; ++i){int tempMask = 0;for(auto j : words[i]){tempMask |= 1 << (j - 'a');}if (__builtin_popcount(tempMask) <= 7) {wordsMask[tempMask]++;}}for(int i = 0 ; i < puzzleCount ; ++i){int sum = 0;int puzzlesMask = 0;for(auto j : puzzles[i]){puzzlesMask |= 1 << (j - 'a');}int tempMask = puzzlesMask;do{int index = tempMask | (1 << (puzzles[i][0] - 'a') );if(wordsMask.count(index)){sum += wordsMask[index];}tempMask = (tempMask - 1) & puzzlesMask;}while(tempMask != puzzlesMask);ans[i] = sum / 2;}return ans;}
};

关键还就是这手二进制子集遍历:

int tempMask = puzzlesMask;do{int index = tempMask | (1 << (puzzles[i][0] - 'a') );if(wordsMask.count(index)){sum += wordsMask[index];}tempMask = (tempMask - 1) & puzzlesMask;}while(tempMask != puzzlesMask);

有点写呲了,这里我的写法把整个谜面取进了mask,导致在后面遍历子集的时候连带着首位的1在遍历,结果就是统计个数翻了一番。

            for(auto j : puzzles[i]){puzzlesMask |= 1 << (j - 'a');}

这里如果改写成下标,不取第一位的话,后面sum就不用/2了

         for(int j = 1 ; j < 7 ; ++j){puzzlesMask |= 1 << (puzzles[i][j] - 'a');}

leetcode 1178.猜字谜相关推荐

  1. 记录一下leetcode:1178猜字谜

    import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream;/*** leetcode ...

  2. LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)

    文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...

  3. leetcode 1178. 猜字谜(位运算)

    外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底: 单词 word 中包含 ...

  4. 【力扣】1178. 猜字谜

    以下为力扣官方题解 1178. 猜字谜 题目 示例 提示 官方题解 前言 方法一 二进制状态压缩 思路与算法 细节 代码 复杂度分析 方法二:字典树 思路与算法 细节 代码 复杂度分析 题目 外国友人 ...

  5. leetcode 1178. Number of Valid Words for Each Puzzle | 1178. 猜字谜(bitmask位运算)

    题目 https://leetcode.com/problems/number-of-valid-words-for-each-puzzle/ 题解 看了答案,堪称力扣最详细的答案,从时间复杂度的角度 ...

  6. 猜字谜 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底:

    今天是元宵节,力扣也细心地为我们准备了一道有关节日的题,一起看看吧: 1178. 猜字谜 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出 ...

  7. Leetcode 猜字谜

    WechatIMG521.jpeg 题目描述 leetcode 第1178题:猜字谜 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如 ...

  8. LeetCode日记_007_猜字谜

    题目信息: 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面puzzle 按字符串形式给出,如果一个单词word符合下面两个条件,那么它就可以算作谜底: 单词word中包 ...

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

    算法–猜字谜(哈希表优化) 元宵节的时候,力扣上的每日一题是这样的: 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 wo ...

最新文章

  1. Windows10下SSH远程拷贝文件
  2. 阿里云联合8家芯片商推“全平台通信模组”,加速物联网生态建设...
  3. oracle中create table with as和insert into with as语句
  4. 1.10 instanceof关键字
  5. CommunityServer 2.0 RTM时间是:2006-02-17 --Scott Watermasysk今天中午
  6. 电脑换ip_代理ip地址怎么换
  7. Linux检查CPU过高的原因
  8. Bailian2980 大整数乘法【大数】
  9. 同济大学 线性代数 第六版 pdf_线性代数同济大学第六版第一章课后习题答案
  10. 不能创建对象qmdispatch_activex部件不能创建对象怎么解决
  11. 抖音视频水印如何去除掉?
  12. linux ipv6修改为ipv4,Linux IPV6 转 IPV4
  13. .rvm/gems/ruby-2.4.1@global/gems/cocoapods-1.5.0/lib/cocoapods/executable.rb:89: warning: Insecure
  14. pwd python 安装 模块_python模块学习之OS、PWD
  15. skyeye linux qt,在ARM9上安装Linux,利用SkyEye模拟器及U-BOOT引导
  16. 利用python爬取京东平台评论及图片并进行分析
  17. android图片系统解决方案-从采集到显示
  18. java最大值最小值_java算法-最大值、最小值
  19. 西北农林科技大学计算机类到底咋样,为了去读985,西北农林科技大学值得选择吗?...
  20. 科大讯飞语音工具类基于Java SDK的封装使用

热门文章

  1. 屏幕截图工具FinalShot for mac
  2. 荆门市龙泉高中2021高考成绩查询,高中学业水平考试成绩查询系统
  3. 15.Java-正则表达式、Pattern和Matcher类、Math类、Random类、System类、BigDecimal类、BigInteger类
  4. usb4与雷电4的区别
  5. QT实现一个Https客户端
  6. 坐而论道,不如起而行之
  7. java中system.getpropery()方法的应用
  8. IBM公司全新的数据仓库解决方案——面向制造零售快速消费品行业的案例
  9. 本科应届生22K拿下字节跳动和顺丰offer,看看你都会吗?
  10. GIt push时出现的Merge branch ‘xxx‘ into ‘xxx‘