剑指offer-第四十题方法总结
2016-05-18 18:34
211 查看
题目:一个数组中只有两个数字单独出现,其余数字都是成对出现的,请找出这两个数。
看到这道题目大多数人第一时间想到的就是排序,排序完成后相邻两个数如果不同,则其中一定有一个是我们要找的数,从这两个数中间将数组分成两部分,分别异或得到的结果就是我们最终要求的两个数。于是我们可以写出下面这样的代码!!!
[align=left]这种方法也可以查找n个单独出现的数。[/align]
[align=left] 好了,现在在加一些限制条件,要求时间复杂度为O(n),空间复杂度是O(1)。[/align]
[align=left] 这时我们就不能进行排序了,但是我们可以借助上面的思想,将整个数组分成两部分,每一部分各包含一个单独出现的数。然后再异或,就能得到结果。[/align]
[align=left]那么问题来了,该怎么样分组呢???[/align]
[align=left] 我们知道,如果两个不相同的数相异或,则得到的结果一定不为0。既然不为0,那么它的二进制位中至少有一位为1。我们只需要找到一个为1的bit位,然后将数组中所有数,按照这一位为0还是为1分成两组,这时就将数组分成了两部分。[/align]
看到这道题目大多数人第一时间想到的就是排序,排序完成后相邻两个数如果不同,则其中一定有一个是我们要找的数,从这两个数中间将数组分成两部分,分别异或得到的结果就是我们最终要求的两个数。于是我们可以写出下面这样的代码!!!
#include<stdio.h> #include<stdlib.h> int check(int arr[], int len) //将arr[]中的数组进行异或,然后将结果返回 { int num = 0; for (int i = 0; i < len; i++) { num ^= arr[i]; } return num; } void bubble_sort(int arr[], int len) //使用冒泡排序,对整个数组进行升序 { int i = 0; int j = 0; int flag=0; for (i = 0; i < len - 1; i++) { flag = 1; for (j = 0; j < len - 1 - i; j++) { if (arr[j]>arr[j + 1]) { arr[j] = arr[j] + arr[j + 1]; arr[j + 1] = arr[j] - arr[j + 1]; arr[j] = arr[j] - arr[j + 1]; flag = 1; } } if (flag) return; } } void check_alone(int arr[], int len, int *num1, int *num2) { bubble_sort(arr, len); int i = 0; for (i = 0; i < len - 1; i+=2) //每次判断两个数 { if (arr[i] != arr[i + 1]) //如果这两个数不相等,则从中间分开,就将数组分成了两部分 { *num1 = check(arr, i + 1); *num2 = check(&arr[i + 1], len - i-1); } } } int main() { int arr[10] = { 0 }; int num1 = 0; int num2 = 0; int len=sizeof(arr) / sizeof(arr[0]); for (int i = 0; i <10; i++) { scanf("%d", &arr[i]); } check_alone(arr,len, &num1, &num2); printf("%d %d\n",num1,num2); system("pause"); return 0; }
[align=left]这种方法也可以查找n个单独出现的数。[/align]
[align=left] 好了,现在在加一些限制条件,要求时间复杂度为O(n),空间复杂度是O(1)。[/align]
[align=left] 这时我们就不能进行排序了,但是我们可以借助上面的思想,将整个数组分成两部分,每一部分各包含一个单独出现的数。然后再异或,就能得到结果。[/align]
[align=left]那么问题来了,该怎么样分组呢???[/align]
[align=left] 我们知道,如果两个不相同的数相异或,则得到的结果一定不为0。既然不为0,那么它的二进制位中至少有一位为1。我们只需要找到一个为1的bit位,然后将数组中所有数,按照这一位为0还是为1分成两组,这时就将数组分成了两部分。[/align]
#include<stdio.h> #include<stdlib.h> int check(int arr[],int len) { int num = 0; for (int i = 0; i < len; i++) { num ^= arr[i]; } return num; } void check_alone(int arr[],int len, int *num1, int *num2) { int i = 0; int ret=check(arr, len); for (i = 0; i < 32;i++) //先找到一位为1的bit位 { if ((ret >> i) & 1) break; } while (len--) //按照这一位将数组分成两部分分别异或 { if (((arr[len] >> i) & 1) == 0) *num1 ^= arr[len]; else *num2 ^= arr[len]; } } int main() { int arr[10] = { 0 }; int num1 = 0; int num2 = 0; int len=sizeof(arr) / sizeof(arr[0]); for (int i = 0; i <10; i++) { scanf("%d", &arr[i]); } check_alone(arr,len, &num1, &num2); printf("%d %d\n",num1,num2); system("pause"); return 0; }
相关文章推荐
- H5之重力感应篇
- jQuery中this与$(this)的区别实例
- childNodes和Children的区别
- js添加触摸时间,禁止页面缩放
- 前端自动化之--gulp
- Invalid action class configuration that references an unknown class解决方案
- [Effective JavaScript 笔记] 第10条:避免使用with
- 模拟 react 框架编码
- jquery select option事件
- js转换 underscore.js学习
- JS获取当前时间戳的方法转换时间戳
- 新手使用React时遇到的问题整理<一>
- JavaScript事件处理指南手册
- CDH5 安装过程
- jQuery验证问题
- html中div+css布局
- js数组排序去重
- html中的滚动标签
- BootStrap的使用文档
- 使用MFC的CHtmlView创建浏览器控件