面试题56 - I. 数组中数字出现的次数(C++)---异或 和 与运算的妙用

题目详情
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例 1:
输入:
nums = [4,1,4,6]
输出:[1,6] 或 [6,1]

示例 2:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]

限制:

  • 2 <= nums <= 10000


——题目难度:中等


 


 

思路
解决这题并且用到异或解法需要以解决136. 只出现一次的数字与运算为基础。


解题顺序
1.先对全员进行异或操作,这样ret就是两个出现一次数字的异或后的结果
2.要想从ret中逆推出那两个只出现一次的数字
就需要进行分组:

  • ① 两个只出现一次的数字在不同的组中

  • ② 相同的数字会被分到相同的组中

②比较好解决,主要是①。
要解决①的话,需要先知道两个出现一次数字的不同点,不同点即一定在某一位上不同(转化为二进制时,如一个数字某一位上是1, 另一个数字那一位为0),而正好两个数异或的结果就是两个数数位不同的直观表现(0即相同,1即不同)
我们可以置一个变量mark(设初值为1)来找到两个数字的数字不同的最低位,通过"while( (ret&mark)==0 ) mark=mark<<1;"循环即可找出这个最低位。

3.随后通过这个最低位可以分别找出那两个只出现一次的数字,还可以满足分组条件②(因为两个相同的数被一个相同条件选择后一定会分到一个组去)。

 

-下面代码

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
    	int n = nums.size(), ret=0, mark=1, a=0,b=0;
		for(int i=0;i<n;i++) //对全员和0做异或处理 
		ret = ret^nums[i];
		
		while( (ret&mark)==0 ){ //找到数字不同的最低位 
			mark=mark<<1;
		}
		
		for(int i=0;i<n;i++)
		{
			if( (nums[i]&mark)==0 ){
				a = a ^ nums[i];
			}else{
				b = b ^ nums[i];
			}
		}
		
		return vector<int>{a,b};
    }
};

结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值