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)放在最后。这时,显然最后的和就等于最后的单值数(前面的项都可以两两相消)。
又由于模二加相当于整型变量的按位异或,故可以很轻易构造程序如下:
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; }
相关文章推荐
- ViewPager的PagerAdapter不可以更新数据
- linux 下利用ls grep 和正则表达式实现目录和文件的分开显示
- facadez模式
- 曹政解密中国互联网
- 如何使用git工作(更新中)
- 技术简历的七要七不要
- 大整数加减 加减运算
- srm 549
- 四倍经验:2010年省队选拔赛山东——大陆争霸
- 三个实例演示 Java Thread Dump 日志分析
- MYSQL 源代码编绎脚本
- Hadoop-调优剖析
- Android完美解决输入框EditText隐藏密码打勾显示密码问题
- HDOJ 4815 Little Tiger vs. Deep Monkey(概率DP)
- 2015 10月10日 工作计划与执行
- mysql删除一条数据后id不在连续的解决方法
- ActiveMQ安装和基本使用
- hdoj 2027 统计元音 C++
- u3d运行过程遇到的小问题(场景会时不时暂停)
- MySQL中char、varchar和text的区别