3 - 数组中数字出现的次数

  1. 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
class Solution {
    
    
public:
    int singleNumber(vector<int>& nums) {
    
    
        /*常规思路
        sort(nums.begin(),nums.end());
        int i=0;
        if(nums.size()==1)
            return nums[0];
        while(i<nums.size())
        {
            if(nums[i]!=nums[i+1])
                return nums[i];
            i+=2;
        }
        return -1;
        */
        //用异或
        int ret = 0;
        for (auto e: nums) ret ^= e;
        return ret;
    }
};
  1. 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
  • 常规解法
class Solution {
    
    
public:
    vector<int> singleNumbers(vector<int>& nums) {
    
    
        vector<int> v;
        int i = 0;
        sort(nums.begin(),nums.end());
        while(i < nums.size())
        {
    
    
            if(i == nums.size() - 1)
            {
    
    
                v.push_back(nums[i]);
                break;
            }
            if(nums[i] ^ nums[i + 1])
            {
    
    
                v.push_back(nums[i++]);
            }
            else
            {
    
    
                i += 2;
            }
        }
        return v;
    }
};
  • 位运算
    从头到尾依次异或数组中的数字,那么最终得到的结果就是两个只出现一次的数字的异或结果,因为其他数字都出现了两次,异或中全部抵消了。由于这两个数字肯定不一样,那么异或的结果肯定不为0,也就是说这个结果的二进制表示中至少有一位为1。我们在结果中找到第一个为1的位的位置,记为第n位。现在我们以第n位是不是1为标准把原数组中的数字分为两个子数组,第一个子数组中每个数字第n位都是1,而第二个子数组中每个数字的第n位都是0。由于我们分组的标准是数字中的某一位是1还是0,那么出现了两次的数字肯定被分配到同一个子数组,于是我们把原数组分为了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。然后再在这个数组中查找只出现一次的数字
class Solution {
    
    
public:
    vector<int> singleNumbers(vector<int>& nums) {
    
    
        int ret = 0;
        for(auto n : nums)
        {
    
    
            ret ^= n;
        }
        int dev = 1;
        while((dev & ret) == 0)
        {
    
    
            dev <<= 1;
        }
        int a = 0,b = 0;
        for(auto n : nums)
        {
    
    
            if(n & dev)
                a ^= n;
            else
                b ^= n;
        }
        return vector<int>{
    
    a,b};
    }
};
  1. 给你一个整数数组 nums ,除某个元素仅出现 一次外,其余每个元素都恰出现三次 。请你找出并返回那个只出现了一次的元素。
  • 从排序数组中查找,但排序需要O(nlogn)
class Solution {
    
    
public:
    int singleNumber(vector<int>& nums) {
    
    
        sort(nums.begin(),nums.end());
        if(nums.size() == 1)
            return nums[0];
        for(int i = 0; i <= nums.size() - 3;)
        {
    
    
            if((nums[i] == nums[i + 1]) && (nums[i + 1] == nums[i + 2]))
            {
    
    
                i += 3;
            }
            else
            {
    
    
                return nums[i];
            }
        }
        return nums[nums.size() - 1];
    }
};
  • 使用哈希表来记录数字出现的次数,但是需要O(n)的空间,时间复杂度为O(n)
class Solution {
    
    
public:
    int singleNumber(vector<int>& nums) {
    
    
        unordered_map<int,int> m;
        for(int n : nums)
        {
    
    
            m[n]++;
        }
        for(int n:nums)
        {
    
    
            if(m[n]==1)
                return n;
        }
        return -1;
	}
}
  • 位运算
    如果一个数字出现三次,那么它的二进制表示的每一位(0或1)也出现三次。如果把所有出现三次的数字的二进制表示的每一位都分别加起来,那么每一位的和都能被3整除。把数组中所有数字的二进制表示的每一位都加起来,如果某一位的和能被3整除,那么那个只出现一次的数字的二进制表示中对应的那一位是0;否则就是1。这种解法的时间复杂度是O(n),空间复杂度是O(1)。
class Solution {
    
    
public:
    int singleNumber(vector<int>& nums) {
    
    
        //时间复杂度是O(n),辅助数组长度固定是32,空间复杂度是O(1)
        if(nums.size()==0)
        {
    
    
            return -1;
        }
        int bitSum[32]={
    
    0};
        for(int n : nums)
        {
    
    
            //要把bitMask设置成unsigned,或者在下面判断是否溢出,否则会出现负数左移报错
            //int:[-2^31,2^31-1];unsigned int[0,2^32-1]
            //unsigned int bitMask=1;
            int bitMask = 1;
            for(int j = 31 ; j >= 0  ; j --)
            {
    
    
                int bit = bitMask & n;
                if(bit != 0)
                {
    
    
                    bitSum[j]++;
                }
                if(bitMask<=INT_MIN||bitMask>=INT_MAX)
                {
    
    
                    break;
                }
                bitMask = bitMask << 1;
            }
        }
        int result=0;
        for(int i = 0 ; i < 32 ; i ++)
        {
    
    
            result = result << 1;
            result += bitSum[i] % 3;
        }
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_41721746/article/details/124019019