LeetCode 89,因为题目晦涩而被点了1500+反对的搜索问题
本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是LeetCode专题第55篇文章,我们一起来看看LeetCode中的第89题 Gray Code(格雷码)。
这题的官方难度是Medium,通过率是48.9%,点赞639,反对1545。又是一道反对比点赞多得多的题目,我个人发现其实这些反对很多的题目都有一个特点,就是题意比较晦涩,出题人的意图不太容易get到。不知道是不是老外理解能力不太行,所以都给出了这么多的反对。
我们就来看看这道题的真面目吧。
题意
题目中说gray code,格雷码是一连串n位二进制表示的数字。这一串的数字有一个特点就是第一个数字是0,从0开始后面的每一个数字和前一个数字只有一个二进制位不同。
题目会给定我们一个非负整数n,要求我们生产n位的灰色代码,也就是产生这些数字。并且这些数字是以10进制存储的。
不知道大家看明白没有,我们来看一个样例。
样例
Input: 2
Output: [0,1,3,2]
在上面这个例子当中,输入是2,表示这些数字是两位二进制位构成的,输出是[0, 1, 3, 2]。我们把0,1,3,2翻译成二进制,0是00,1是01,3是11,2是10。排列在一起的话就是00, 01, 11, 10。我们可以发现每一个数和前一个数相差的都是一个二进制位。
题目当中相关的描述就这么多,但其实有很多隐藏的信息没有给,要我们自己猜测。比如说每一个数字只能出现一次,不然的话这个序列就是无穷无尽的。另外一个隐藏信息是,这样的序列应该也不是唯一的,但是题目并没有说是否所有合法的序列都可以通过测试,还是说一定要返回字典序最小的结果。
题目比较晦涩也就算了,这些隐藏信息没有交代清楚,也难怪大家会费解。
题解
当然以上的问题其实也不是事,我们不确定试一次也就知道了,核心还是怎么想出解法来。
干想是没有结果的,还是要先分析搜集一些信息。首先,题目给定的n,限制了每个数能够使用的二进制位的数量。n个二进制位一共能表示的数字有$2^n$种,我们无法得知是否这么多数字都能串联起来。假设可行的话,那么这个问题其实就是这$2^n$个数如何摆放的问题。
所以问题的关键就是要寻找这样一个序列,根据我们之前解全排列以及各种排列的方法,可以联想得到,这大概率是一个搜索问题。
顺着搜索的思路继续往下,剩下的事情就容易了,我们的起始搜索点是0。题目中要求了每两个相邻的数的二进制位只相差一个,那么我们可以遍历这些二进制位,寻找0的后继节点。同样对于每一个后继节点来说,我们都可以用同样的方法寻找它的后继们。再加上gray code不能包含重复的元素,我们可以在搜索的时候加上剪枝。
这一套其实是一个经典的搜索问题的流程。
如果我们换个思路,虽然也能得到一样的解法,但是思考的过程会不太一样。怎么换思路呢,其实也简单,我们把它想象成一个图论问题。也就是说,每一个数字都是图中的一个节点。如果两个数字之间满足只相差了一个二进制位,那么说明它们之间有一条边相连。整个问题就转变成了我们从0这个点出发,找出所有连通的节点。
对于图上的遍历问题,方法就很固定了就是搜索。也就是说从这个角度思考的话,更加容易想到搜索上面了, 整个思考的链路会更短。这也是为什么很多大神建模的时候喜欢从往图上考虑的原因。
这些都想明白了再来写代码真的就水到渠成了,整个核心代码真的不长:
class Solution:
def grayCode(self, n: int) -> List[int]:
ret = [0]
elements = {0}
def dfs(cur):
# 遍历与cur唯一不同的二进制位
for i in range(n):
# 针对这一维做亦或,将0变1,1变0
nxt = cur ^ (1 << i)
if nxt in elements:
continue
# 记录答案,继续往下遍历
elements.add(nxt)
ret.append(nxt)
dfs(nxt)
dfs(0)
return ret
总结
单纯从思路以及最后的AC代码来看的话,这道题难度应该是很低的,实际上也的确如此,这题的通过率接近50%,已经是Medium难度的下届了。但是相比于做对这题而言,更加重要的是思路。以图论的思维来抽象建模是算法题当中一个非常常见的手段,这是比题目本身更加宝贵的东西。
如果你读过昨天的文章的话,会发现昨天的87题,本质上也是用的一个图论建模的方法。但是从表现形式上来说,这两题真的可以说是完全不一样。建议大家能好好做做这两题,体会一下其中思维和解法的闪光点。
今天的文章到这里就结束了,如果喜欢本文的话,请来一波素质三连,给我一点支持吧(关注、转发、点赞)。
本文使用 mdnice 排版
LeetCode 89,因为题目晦涩而被点了1500+反对的搜索问题的更多相关文章
- leetcode - 位运算题目汇总(下)
接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目. Bitwise AND of Numbers Range 给出一个范围,[m, ...
- leetcode top 100 题目汇总
首先表达我对leetcode网站的感谢,与高校的OJ系统相比,leetcode上面的题目更贴近工作的需要,而且支持的语言广泛.对于一些比较困难的题目,可以从讨论区中学习别人的思路,这一点很方便. 经过 ...
- [LeetCode] 89. Gray Code 格雷码
The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...
- leetcode tree相关题目总结
leetcode tree相关题目小结 所使用的方法不外乎递归,DFS,BFS. 1. 题100 Same Tree Given two binary trees, write a function ...
- All LeetCode Questions List 题目汇总
All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...
- [LeetCode] 二叉树相关题目(不完全)
最近在做LeetCode上面有关二叉树的题目,这篇博客仅用来记录这些题目的代码. 二叉树的题目,一般都是利用递归来解决的,因此这一类题目对理解递归很有帮助. 1.Symmetric Tree(http ...
- [LeetCode] 动态规划入门题目
最近接触了动态规划这个厉害的方法,还在慢慢地试着去了解这种思想,因此就在LeetCode上面找了几道比较简单的题目练了练手. 首先,动态规划是什么呢?很多人认为把它称作一种"算法" ...
- 关于LeetCode上链表题目的一些trick
最近在刷leetcode上关于链表的一些高频题,在写代码的过程中总结了链表的一些解题技巧和常见题型. 结点的删除 指定链表中的某个结点,将其从链表中删除. 由于在链表中删除某个结点需要找到该结点的前一 ...
- LeetCode - 排列相关题目
1.获取全排列 https://leetcode.com/problems/permutations/submissions/ 按字典序输出: 这里用的是vector<int>,不是引用. ...
随机推荐
- 数据可视化基础专题(三):Pandas基础(二) csv导入与导出
1.csv导入 1.1 csv导入 .read_csv()函数 pandas.read_csv(filepath_or_buffer: Union[str, pathlib.Path, IO[~Any ...
- Python函数07/有参装饰器/多个装饰器装饰一个函数
Python函数07/有参装饰器/多个装饰器装饰一个函数 目录 Python函数07/有参装饰器/多个装饰器装饰一个函数 内容大纲 1.有参装饰器 2.多个装饰器装饰一个函数 3.今日总结 3.今日练 ...
- MapReduce计算框架的核心编程思想
@ 目录 概念 MapReduce中常用的组件 概念 Job(作业) : 一个MapReduce程序称为一个Job. MRAppMaster(MR任务的主节点): 一个Job在运行时,会先启动一个进程 ...
- 【Nginx】如何按日期分割Nginx日志?看这一篇就够了!!
写在前面 Nginx是没有以日期格式作为文件名来存储的,也就是说,Nginx不像Tomcat,每天自动生成一个日志文件,所有的日志都是以一个名字来存储,时间久了日志文件会变得很大.这样非常不利于分析. ...
- 怎样从gitHub上面拉项目
1.注册 https://gitee.com/oschina 2.拿到代码在gitHub上的地址 3.打开eclipse-->import https://git.oschina.net/cai ...
- 年薪30W+高薪测试技术要掌握哪些?
职业技能一 1. 软件测试: 1) 熟练灵活地运用等价类.边界值.判定表法.因果图法等各种方法设计测试用例,包括单元测试.集成测试.系统测试用例设计. 2) 牢固掌握了软件测试计划.测试日报.测试报告 ...
- ES6语法——let和const
一.let 1.定义 ES6新增了let命令,用来声明变量,用法类似于var,但是和var有一定的区别 2.let只在块级作用域内有效 首先来看一个比较简单的例子,请告诉我,他们分别输出什么 //代码 ...
- 阿里云如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器?
阿里云如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器? 见如上链接中视频
- eclipse IDE usage of my own and tutorials link list
设置 字符集 Eclipse 修改字符集 默认情况下 Eclipse 字符集为 GBK,但现在很多项目采用的是 UTF-8,这是我们就需要设置我们的 Eclipse 开发环境字符集为 UTF-8, 设 ...
- Ribbon 负载规则替换
1 添加规则类: 注意: 官方文档明确给出了警告: 这个自定义配置类不能放在 @ComponentScan 所扫描的当前包下以及子包下,否则自定义的配置类就会被所有的 Ribbon 客户端所共享,达不 ...