您的位置:首页 > 其它

LeetCode:Single Number

2015-10-10 13:53 169 查看
Given an array of integers, every element appears twice except for one. Find that single one.

Note:

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

My Solution:

1. 搜索,对每个输入的整数,判断能不能搜索到另一个相同的整数。“对每个”和“搜索”各需要一次循环遍历,需要O(n^2)的复杂度,不满足题意。

2. 排序,然后按两两一组寻找落单的数。这样肯定有解,但一旦加入排序,时间复杂度就不可能是线性的了。最快也是O(nlgn)。

3. 按照位图排序的想法,对每个输入的整数,以其为下标或索引,控制数组中的对应位置的变量的值。最后根据值判断该数出现了几次。但这个方法有两个问题,一个是输入的整数可能是负数,这个问题可以将整数转化为无符号整数来解决。但第二个问题是,整数的范围过大,不可能开一个长度是2^32的数组。如果按照输入数组大小进行哈希的话,对于有冲突的数该如何处理?如果放一个链表数组,全都挂到相同位置的话,那最终对有奇数个元素的链表,还要再进行一次小规模的搜索。最坏的情况下,如果所有的输入整数都有相同的哈希值,那么这个问题就无限递归了。

4. 要算法既满足线性复杂度,又不用过多空间的话,最理想的是有一个状态机,可以和整数进行运算,对同一整数运算两次会返回原状态,且运算要满足交换律和结合律。所以现考虑加法和乘法。

如果有有一个累加器,第一次加上某个数,第二次遇到这个数时再减去它。这样最后就只剩下那个只出现了一次的数了。

或者乘法器,对同一个值的数,第一次乘,第二次除。

或者将这个数组中每个值不同的元素都对应到一个质数(值相同则对应的质数相同),求它们的乘积,最后再做质因数分解。

想了好几种类似的办法。质数的想法,光做到“值相同则对应的质数相同”这一点的时间复杂度就不止O(n)了,而乘法器的方法,我想不出有什么可以做到对同一个数第一次做乘法第二次做除法。

最后有希望的还是累加器。虽然没办法控制加法的符号,但如果把数字按二进制写出来,进行模二加的话,那么对同一个数,加两次后每位必然为0。我们将所有的数进行模二加,由于满足交换律和结合律,可以任意交换每一项,我们就可以把值相同的项放在一起,把单值数(Single
Value)放在最后。这时,显然最后的和就等于最后的单值数(前面的项都可以两两相消)。

又由于模二加相当于整型变量的按位异或,故可以很轻易构造程序如下:

int singleNumber(int* nums, int numsSize) {
int base = 0;
while(numsSize-- > 0)
{
base ^= *nums;
++nums;
}
return base;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: