这个系列是写给找工作前的我看的,毕竟作为一个记性很差的人,可能过一段时间又忘了怎么写了。。。然后作为开胃菜的第一题就没有思路,真的是让人非常有挫败感了。。。
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
解题思路来源于此链接:https://cuijiahua.com/blog/2018/01/basis_40.html
以下是有用内容的摘录:
大家首先想到的是顺序扫描法,但是这种方法的时间复杂度是O(n^2)。接着大家又会考虑用哈希表的方法,但是空间复杂度不是O(1)。
应该怎么做才能即满足时间复杂度是O(n)又满足空间复杂度是O(1)的要求呢?
我们可以想一想“异或”运算的一个性质,我们直接举例说明。
举例:{2,4,3,6,3,2,5,5}
这个数组中只出现一次的两个数分别是4和6。怎么找到这个两个数字呢?
我们先不看找到俩个的情况,先看这样一个问题,如何在一个数组中找到一个只出现一次的数字呢?比如数组:{4,5,5},唯一一个只出现一次的数字是4。
我们知道异或的一个性质是:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字。比如数组{4,5,5},我们先用数组中的第一个元素4(二进制形式:0100)和数组中的第二个元素5(二进制形式:0101)进行异或操作,0100和0101异或得到0001,用这个得到的元素与数组中的三个元素5(二进制形式:0101)进行异或操作,0001和0101异或得到0100,正好是结果数字4。这是因为数组中相同的元素异或是为0的,因此就只剩下那个不成对的孤苦伶仃元素。
位运算小结(按位与、按位或、按位异或、取反、左移、右移):https://blog.csdn.net/mengzhengjie/article/details/80611422
摘录:
按位异或(^)
参加运算的两个数,换算为二进制(0、1)后,进行异或运算。只有当相应位上的数字不相同时,该为才取1,若相同,即为0。
1 2 3 4 5 6 |
|
可以看出,任何数与0异或,结果都是其本身。利用异或还可以实现一个很好的交换算法,用于交换两个数,算法如下:
1 2 3 |
|
class Solution {
public:
int singleNumber(vector& nums) {
int result = 0;
for(int i = 0;i < nums.size();i++)
{
result = result ^ nums[i];
}
return result;
}
};