题目来源:链接: [https://leetcode-cn.com/problems/single-number-ii/].
137.只出现一次的数字 II
1.问题描述
Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
示例1:
Input: [2,2,3,2]
Output: 3
示例1:
Input: [0,1,0,1,0,1,99]
Output: 99
2.我的解决方案
先将给出的数组集合 排序 ,然后 比较 前后两个 元素 是否与当前元素相同,都不相同则 表示 此元素 值出现了一次。
注意 考虑 首尾两个情况。
时间复杂度为O(n)
我的AC代码如下:(这里使用的是暴力法,接下来有使用位操作的解法)
class Solution {
public:
int singleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int res = 0;
int nums_size = nums.size();
//两次 特殊处理
if(nums_size == 1 || nums[0] != nums[1] )
{
return nums[0];
}
if(nums[nums_size - 2] != nums[nums_size - 1])
{
return nums[nums.size()-1];
}
//遍历
for(int i = 1; i < nums_size - 1; ++i)
{
if(nums[i] != nums[i-1] && nums[i] != nums[i+1])
{
res = i;
}
}
return nums[res];
}
};
3.大神们的解决方案
大神用位的神奇方法。(感觉虽然懂了,但是有点特例,不能泛化,当做训练吧)
详细解释一下:
一:基础知识
假设有一个数为x,那么则有如下规律:
0 ^ x = x,
x ^ x = 0;
x & ~x = 0,
x & ~0 =x;
二:本题解答
接下来就很好解释下面的代码了。
一开始 a = 0, b = 0;
x第一次出现后,a = (a ^ x) & ~b的结果为 a = x,
b = (b ^ x) & ~a (此时a = x),所以结果为b = 0。
即 a = 0 , b = 0;
x第二次出现:a = (a ^ x) & ~b, a = (x ^ x) & ~0, a = 0;
b = (b ^ x) & ~a 化简, b = (0 ^ x) & ~0 ,b = x;
x第三次出现:a = (a ^ x) & ~b, a = (0 ^ x) & ~x ,a = 0;
b = (b ^ x) & ~a 化简, b = (x ^ x) & ~0 , b = 0;
所以出现三次同一个数,a和b最终都变回了0.
只出现一次的数,按照上面x第一次出现的规律可知a = x, b = 0;因此最后返回a.
class Solution {
public:
int singleNumber(vector<int>& nums) {
int a = 0, b = 0;
for (auto num : nums)
{
a = (a ^ num) & ~b;
b = (b ^ num) & ~a;
}
return a;
}
};
4.我的收获
位运算要系统的学习下,感觉 有很多巧妙的地方。
2019/7/13 胡云层 于南京 123