每日刷题:力扣137.只出现一次的数字II

题目:只出现一次的数字II

给你一个整数数组 nums ,除某个元素仅出现一次外,其余每个元素都恰出现三次。请你找出并返回那个只出现了一次的元素。

示例1

输入:nums = [2,2,3,2]
输出:3

示例2

输入:nums = [0,1,0,1,0,1,99]
输出:99

代码1:

思路参考力扣热评: 传送门

class Solution {
    public int singleNumber(int[] nums) {
        int a=0,b=0;
        for(int i=0;i<nums.length;i++){
            b = (b ^ nums[i]) & ~a;
            a = (a ^ nums[i]) & ~b;
        }
        return b;
    }
}

解析:
一个二进制位可以记录出现一次还是两次,所以要记录三次则需要两个二进制位。

注意此题中前提为除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
注意位运算符与(&)、或(I)、非(~)、异或(^)是针对二进制数的位进行逻辑运算。

要使

a b
①:0 0 (+) 1 = 0 1
②:0 1 (+) 1 = 1 0
③:1 0 (+) 1 = 0 0 ( mod 3)

则需要当:

b=0时,a运算为与运算(①)和或(异或)运算(②)。
b=1时,a运算结果为1(或运算)。
a=0时,b运算为异或运算
a=1时,b运算结果为0(与运算)。

满足这个条件成立的公式显然一眼是看不出来的,所以看后面

然而要注意——运算是有先后顺序的,也就是说a,b不一定同时先判断而后运算。所以可以当b先运算,则:

b=0时,a运算为异或(②、③)
b=1时,a运算结果为0(①)
a=0时,b运算为异或(①、②)
a=1时,b运算结果为0(③)

这个条件看起来就好有规律的样子,那么有没有对应足够简单的公式呢?

注意:
ab ^ 0 = ab ; ab ^ ab = 0;
x & ~x = 0 ; x & ~ 0 = x ;

则可以:

b = (b ^ nums[i]) & ~a;
a = (a ^ nums[i]) & ~b;

此时满足之前两个二进制数记录三次的条件,所以当所有数(int)全部运算后,对应二进制位中3个重复的会消掉,多出来的就是那只出现一次的数了

a先运算的情况我没有推,不知道能不能找到对应且足够简单的公式= =

你可能感兴趣的:(leetcode)