快使用位运算!解决只出现一次的数字(LeetCode)

137 只出现一次的数字 II
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
输入: [2,2,3,2]
输出: 3
链接:https://leetcode-cn.com/problems/single-number-ii

位运算复习

~非运算~0 = 1,~1 = 0例:~10101 = 01010
&与运算1&1 = 1 ,1&0 = 0,0&0 = 0例:10010&00110 = 00010
|或运算1|1 = 1,1|0 = 1,0|0 = 0例:1100101|1001100 = 1101101
^异或运算1^1 = 0,1^0 = 1,0^0 = 0例:10010^01110 = 11100
<<左移向左移动N位,0填补例:10010<<3 = 10010000
>>右移向右移动N位,0填补例:10010>>3 = 00010

位运算解法

解法思路来自:https://leetcode-cn.com/problems/single-number-ii/solution/single-number-ii-mo-ni-san-jin-zhi-fa-by-jin407891/
感觉比官方的位运算好理解,豁然开朗。

一个概念:异或 实际上是做不进位的加法
1^0 = 1 + 0 = 1
1^1 = 看作 1+1 但我们不进位 = 0
即如果是在一组出现偶数次的数中寻找只出现一次的数,那就是所有数做异或运算的结果。
所以,我们的题目是在出现三次的数组中找出现一次的数,那我们就相当于实现一个三进制的异或运算。
这样,我们的关键就在于如何实现一个三进制的异或
我们需要构建三个变量来记录出现的次数:one、two、three 来对数组nums 进行遍历。

one : 二进制某位出现2次时ones = 0,出现1, 3次时ones = 1
two : 二进制某位出现1次时twos = 0,出现2, 3次时twos = 1
three:二进制某位出现3次时(即twos = ones = 1时)three = 1,其余即出现1, 2次时three = 0;

然后我们对one,two实现一个三进制的一个异或,即将出现三次的位归零。
这样 one 的最终结果就是出现一次的那个数
具体代码如下:

public int SingleNumber(int[] nums) {
	int one = 0;
	int two = 0;
	int three = 0;
	foreach (var n in nums)
	{
		two |= one&n;
		one ^= n; 
		three = two & one;
		one &= ~three; // 将二进制下出现3次的位置零
		two &= ~three;
	}
	return one;
   }

时间复杂度:O(n) 空间复杂度:O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值