求数组中只无重复的数

是真的菜

题目

  • Given an array of integers, every element appears three times except for one. Find that single one.
  • 代码及思想:

    class Solution {
    public:
        /*
        思路:
            既然数组中重复数的个数为3,那么只要计算每个bit位的和是否为1就行
            比如三个重复数他的某个bit位要么全是1要么全是0,相加的话要么是1+1+1=3,或者是0+0+0=0
            然后不重复的那个数该bit位为1的话则总和为4或者1,为0的话其总和为3或者0
            总和模3后即不重复的那个数的bit位上的数字
        同理推得,如果重复的数的个数为m的话就模m就ok
        */
        int singleNumber1(int A[], int n) {
            if(n==1)
                return A[0];
            int res = 0;
            for(int i=0;i<32;i++)
            {
                int bits = 0;
                for(int j=0;j<n;j++)
                    bits += ( (A[j] & (1<<i)) >> i );
                res |= ((bits%3) << i);
            }
            return res;
        }
    
        /*
        思路2:
            用ones记录出现一次的bits数
            tows记录出现两次的bits数
            threes记录出现三次的bits数
        */
        int singleNumber1(int A[], int n) {
            if(n==1)
                return A[0];
            int ones = 0;
            int twos = 0;
            int threes = 0;
            for(int i=0;i<n;i++)
            {
                twos |= ones & A[i]; //用&,如果bit位出现两次则为1,不然为0
                ones ^= A[i];
                threes = twos & ones; //如果twos和ones上的bit位为1则表示出现3次了,所以用&
                ones &= ~threes; //ones中去除出现三次的bit位
                twos &= ~threes; //twos中去除出现三次的bit位
            }
            return ones;
        }            
    };
    

扩展

  • 如果重复的数的次数为2?
  • 答:直接遍历异或
  • 如果重复的数的次数为m(m>2)?
  • 答:方法1模m
  • 如果重复的数的次数为2,但是不重复的有2个数?
  • 答:先遍历异或一遍得到一个数,找到这个数bit位为1的位置,按照这个bit位是否为1将整组数分成两组(不重复的两个数必定分在不同组)
  • 如果重复的数的次数为m(m>2),但是不重复的有2个数?
  • 答:用方法1找bits模m为1的bit位,按照这个bit位是否为1将数组分成两组(模m为1表示两个b不重复的数在这个bit位上是不同的);然后按照方法1分别求不重复的一个数