1

single number i

  • 题目:有一个数据只出现一次,其他数据都出现两次

  • 思路:位运算(亦或)

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        for(int i = 1; i < nums.size(); i++)
          nums[0] = nums[0] ^ nums[i];
        return nums[0];
    }
};

single number ii

  • 题目:有一个数据只出现一次,其他数据均出现3次

  • 思路:位运算

    • 写成2进制数后,对每一位求和(其实是统计每一位出现1的次数),因而可见由重复数据求得的每一位和应该都是3的倍数,因而求余即可知道只出现1次的数据。

      class Solution:
        def singleNumber(self, nums):
            re = [0]*32
            for num in nums:
                for i in range(32):
                    re[i] += (num >> i) & 1
            result = 0
            for i in range(32):
                   result += (re[i] % 3) * pow(2, i)
            return result
    • 现在的复杂度是32*O(N),仍然是线性时间,常数空间。

    • 有更简单的方法,更复杂的位运算,不过我表示虽然复杂度更低,然而我理解无能,先贴在这里吧。

        class Solution:    
            def singleNumber(self, A):  
                   ones,twos=0,0  
                for ele in A:  
                    ones = ones^ele & ~twos  
                    twos = twos^ele & ~ones  
                return ones 

single number iii

  • 题目:只有两个数据出现一次,其他都出现两次

  • 思路:当然是位运算

    • 如果只有一个数据只出现一次的话,很简单的求亦或。

    • 两个的话自然有不同。但是我们可以知道的是,若a,b为所求,则前面累计的亦或值re = a^b,而re中为1的数位即是a和b中一个为1一个为0的。

    • 我们随机取一位,那么所有数据可以分成两组。一组该位为1,另一组为0,而a和b分别在这两组中。同样地,我们可以看到,除了a和b之外,每组其他的数据都出现2次。这样我们就转化成了上述的简单求亦或。

    • 因而问题变成,取得re中某为1的数位,将数据分成两组

      class Solution(object):
            def singleNumber(self, nums):
                re = 0
                for num in nums:
                    re ^= num
      
                n = re & (~(re - 1))#取为1的最低位
                a = 0
                b = 0
                for num in nums:
                    if n & num:#将数据按该为是否为1分成两组
                        a ^= num
                    else:
                        b ^= num
                return a, b

sophia_49
5 声望2 粉丝