面试题56 - I. 数组中数字出现的次数(Leetcode)最简单解释

有简单版的一道题:一组数中有一个是成单出现的,其余是成双出现的,问那个数是成单出现的。
计算机中的运算时二进制运算,因此有位运算的出现。而这道题主要是考察异或交换律
异或:同为相反为1,相同为0 例如 1^0=1 0^1=1 1^1=0 0^0=0
比如:数组 a[]:1 2 1 初始sum=1 用sum记录3次异或值:
在这里插入图片描述
第一次:0^1=1
第二次:01^10=11
第三次:11^01=10

当数组a[]:2 1 2 3 3 时:
在这里插入图片描述
同理,这个太多了我就懒得写了(●’◡’●)
通过异或可以找出一个成单的数。
现在题目是:一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
限制:
2 <= nums <= 10000
题目链接
有一种方法就是把数组分为2组,在每一组里面找到那个成单的数。答案为a,b;

  1. 把数组里面所有的数异或一遍 (得出来的异或值是两个成单数的异或值,也就是a^b=sum)
  2. 把sum和-sum进行与运算(k=sum&(-sum) k保留sum的最后一个1,通过这个1我们来进行分类。两个数相同的一定回到一组,同时a,b回分到不同的两组)
  3. 遍历分组
  4. 得到答案
    分组关键:两个数位不同为1,那么找到sum中任意一个1,那就可以确定a,b的分组。
class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
         int sum = 0;
         int n=nums.size();//
      for (int i = 0; i < n; i++) { 
        sum ^= nums[i];
    }
    int k = sum & (-sum);//分为两组的关键
    int a = 0;
    int b = 0;
    for (int num:nums) {
        if (num & k) {//分组策略
            a ^= num;
        }
        else {
            b ^= num;
        }
    }
    return {a,b};//返回每组成单的值
}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值