136-只出现一次的数字
https://leetcode-cn.com/problems/single-number/
137-只出现一次的数字II
https://leetcode-cn.com/problems/single-number-ii/
260-只出现一次的数字III
先看136,位运算的经典题,知乎凡是有吹位运算的回答的,没有不拿这题开刀的。
原理是a ^ b ^ b = a
1 | public int singleNumber(int[] nums) { |
跳过137,先看260题,相比136题它从一个数变成了两个数,难度大了很多
思路:
我们假设只出现一次的两个数为a, b,按照136题的思路,遍历异或,得到的结果应该是res = a ^ b
res中二进制为1的位就是a和b二进制不一样的位,不管哪个1,我们可以将这个位为1的所有数和这个位为0的所有数分开,那么就可以得到两组数
a, c, c
b, d, d
又成为了136题的情况
1 | public int[] singleNumber(int[] nums) { |
137题
这题放到最后讲是因为说实话比较难,难在前面的是其他元素出现两次,而“异或”这个位运算刚好使得b^b=0。这题难在出现了3次,意味着我们需要设计一个“运算”,使得b★b★b=0
评论区的代码大多是这样的,却没解释清楚
1 | public int singleNumber(int[] nums) { |
我认为解释的最好的是题解的这一篇
简单解释就是3种状态需要两位,所以从00,01,10,11四个中任选3个,比如00,01,10,那么需要画真值表使其满足00->01, 01->10, 10->00
Z是什么,Z为1代表这个数出现了,那么
一开始为00,Z第一次出现00->01,第二次出现01->10,第三次出现10->00
那么就可以写表达式了,根据数电的知识,写x_new只看x_new为1的
事实上,我认为到这一步就够了,化简什么的一时半会写不出来,那么我们就以这个为例,写的时候要注意,不要直接变x而是用x_new存起来,否则计算y_new时改变了x的值。当然,python可以a, b = b, a另说
1 | public int singleNumber(int[] nums) { |
至于化简完,就是前面贴的那个样子了,我数电不好,靠你们了
其他题目点击这里