陆续做完了关于^&|
的题目,在此想总结下。
只出现一次的数字I
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗
示例 1:
1
2
3 > 输入: [2,2,1]
> 输出: 1
>
示例 2:
1
2
3 > 输入: [4,1,2,1,2]
> 输出: 4
>
^
运算有很多性质在这里我们需要知道的是:
- 零与任何数
^
为任何数 - 任何数与其自身
^
为零,并且具有交换律。
[1, 2, 2, 3, 3] ==> 1^2^2^3^3 = 1
^
的交换律体现在 [2, 1, 2, 3, 3] ==> 2^1^2^3^3 = 1
从上述例子可知,如果一个序列中某些数字出现两次可以通过^
将其消去,最后的结果为该数列中出现一次的数字。
1 | class Solution { |
只出现一次的数字 II
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
1
2
3 > 输入: [2,2,3,2]
> 输出: 3
>
示例 2:
1
2
3 > 输入: [0,1,0,1,0,1,99]
> 输出: 99
>
第一题我们谈到了^
的神奇之处,但这里是三个同样的数字,这样第一题的方法就失效了。
由于整数在计算机内表示很简单,由一系列01的组合构成,我们可以开辟一个32位的数组,存储int
的每一位01。 由于有三个相同的数字,当某一位上的1之和为3,将其置为0。重复上面的过程,最后的数组里存储就是唯一出现一次的元素的32位01的组合,最后将其转换成十进制。
下面代码有两个位置需要注意下
- 第8行,将十进制转换成二进制,其实也就是辗转相除法,向左移一位相当于除以二。
- 第16行,想将1移到对应的位上,然后做
|
运算,就可以将该数字转换成十进制。
1 | class Solution { |
只出现一次的数字 III
260. 只出现一次的数字 III
给定一个整数数组
nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。示例 :
1
2
3 > 输入: [1,2,1,3,2,5]
> 输出: [3,5]
>
根据第一题给出的结论,将序列中所有的数字都^
则剩下的就是两个唯一出现一次元素的^
的结果。如[1,2,1,3,2,5]全部^
一次结果是 3^
5。将序列分为两组,分组是根据3和5低位的1来分的,从低位开始如果011(3)和101(5),我们选取第二位来作为划分该序列的标准,第二位为1的和3一组,第二位不为1的和5一组。最后再利用第一题的结论,做一次^
运算就可以把两个只出现一次的元素找出来了。
3^5
= (0100)2 第三位可以作为区分两组不同数字的依据,但不是所有的数字都像3和5这么短小,故要使用低位运算将其截取到最低位的1和后面所有的0。
低位运算
lowbit(w)
定义为非整数n
在二进制表示下“最低位的1及其后面的所有0”构成的数值
如: n = 10,二进制表示为(1010)2, 则其低位lowbit(10) = (10)2 = 2.
公式有: lowbit(n) = n & (~n + 1) = n & ( - n )
1 | class Solution { |