[LeetCode] 260. Single Number III

论坛 期权论坛 脚本     
匿名技术用户   2021-1-7 09:42   54   0

题目:

Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

答案:

思路:

这道题是136. Single Number的一个变种,由此引出了这一类问题的解法。我们可以把这类问题归纳描述为:一个数组中所有的数字都出现了K(的倍数)次,只有一个数字出现了一次,求这个数。思路是我们要记录数字出现的次数,当出现了K次的时候就等价于它出现了0次。这个可以通过数字电路的计数器来实现。

比如说当K=2,我们的要设计的计数器就是有2个状态:0,1。当计数为2时又变回0。这样我们的计数器就需要1个bit去存储所有的状态。然后我们要考虑计数器的状态转换。假设原状态为a,然后新来的bit是b那么我们有:当a=0, b=1 || a=1,b=0的时候新状态为1,也就等价于(~a&b)||(a&~b) = a^b。所以这就是我们要求异或的原因。

同样的,当K=3的时候,我们要设计的计数器就有3个状态:0,1,2。我们就需要2个bit去存储所有的状态。假设我们用a,b表示计数器的两个位,c表示新来个bit,那么计数器的逻辑就是a = a&~b&~c + ~a&b&c;b = ~a&b&~c + ~a&~b&c,这个推导过程留给读者。最后的结果,当计数为0的时候结果是0,当计数不为0的时候结果为1,也就是a|b。

注意上面说的1-bit或者2-bit计数器都只是记录最后结果的一个bit的状态的,由于输入/输出是Integer,所以我们需要32个这样的计数器,也就是用1个或者2两个Integer来表示。

参考代码:

public class Solution {
    public int singleNumber(int[] nums) {
        int a = 0,b = 0;
        for(int i = 0; i < nums.length; i++) {
            int temp = (~a&b&nums[i]) | (a&~b&~nums[i]);// a的新状态保存在temp中,因为b的新状态要根据a原来的状态推导出来
            b = (~a&~b&nums[i]) | (~a&b&~nums[i]);
            a = temp;
        }
        
        return a|b;
    }
}

参考阅读:

https://discuss.leetcode.com/topic/22821/an-general-way-to-handle-all-this-sort-of-questions

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP