创造不易,可以点点赞吗~
如有错误,欢迎指出~
单身狗1
题述
在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。
例如:数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5
分析
我们可以用按位异或操作符解决
其中根据 按位异或的特点(同为0,异为1)
- n^0==n;
- n^n==0;
如下代码中0分别与数组元素按位异或,如第一次0^1==1,1^1==0……直到最后0^5==5找到了单身狗。
代码
#include<stdio.h> int main() {int arr[9] = { 1,2,3,4,5,1,2,3,4 };int sz = sizeof(arr) / sizeof(arr[0]);int n = 0;for (int i = 0; i < sz; i++){n = n ^ arr[i];}printf("单身狗是%d", n);return 0; }
结果
单身狗2
题述
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
只有5和6只出现1次,要找出5和6.
分析
分3步走
1.将所有数字异或
将数字1,2,3,4,5,1,2,3,4,6全部相互异或得到5和6的异或结果0011
5 0101 6 0110
1 0001 2 0010
4 0100 3 0011
2.确定二进制位1的不同处
其中5,1,4的倒数第二位都为0,而6,2,3的倒数第二位都为1
3.将5,1,4分为一组,6,2,3分为一组,最后将他们分别异或得到结果
代码
#include<stdio.h> void find_num(int arr[], int n, int* pn1, int* pn2) {//1.将所有数字异或int ret = 0;for (int i = 0; i < n; i++){ret ^= arr[i];}//最后得到的结果是5和6的异或int pos = 0;//2.确定ret二进制为1的位置for (int i = 0; i < 32; i++){if ((ret >> i) & 1 == 1){pos = i;break;}}//3.分组,pos为1的一组,pos为2的一组for (int i = 0; i < n; i++){if ((arr[i] >> pos & 1) == 1){*pn1 ^= arr[i];}else{*pn2 ^= arr[i];}} } int main() {int arr[] = { 1,2,3,4,5,1,2,3,4,6 };int len = sizeof(arr) / sizeof(arr[0]);int n1 = 0;int n2 = 0;find_num(arr, len, &n1, &n2);printf("单身狗是%d和%d\n", n1, n2);return 0; }
运行结果