一个数组中只有两个数字是出现一次, 其他所有数字都出现了两次。 找出这两个数字,编程实现。

/*
一个数组中只有两个数字是出现一次,
其他所有数字都出现了两次。
找出这两个数字,编程实现。
*/

//思路:
//一个数与另个数异或两次,结果为原数.
//1.考虑将两个只出现一次的数分别放到两个不同的数组中;
//2.保证1的条件下,不能使出现两次的数分到不同数组中;
//3.两个不同的数异或,总有至少一个二进制位为1;
//4.其中的1就是这两个数的分歧点;
//5.可以任取一个为1的二进制位对数组元素进行分组.
//所以先让数组各元素与0异或,最终得两个只出现一次的数的异或结果
//再找到这个数的最低且为1的二进制位,利用这一点将数组元素分组,
//最后用0分别与两数组中的元素异或,就得到两个只出现一次的数.

#include<stdio.h>
#include<stdlib.h>

//找一个数的最低且为1的二进制位函数
int find_min1_bit(int n){
	int count = 0;  
	int i;
	for (i = n; i; i >>= 1){  //遍历n每一位
		if (i & 1 == 1){  //若i此时的最低二进制位为1
			break;  //跳出循环
			}
		else{
			++count;  //count加1
		}
		}
	return count;
}

//找一个出现一次的数函数(返回该值)
int first_occur_number(int arr[],int len){
	int i;
	int num = 0;
	for (i = 0; i < len; ++i){  //遍历异或,找只出现一次的数
		num ^= arr[i];
	}
	return num;     
}

//利用二进制位分解数组函数
void divide_array_by_bit(int arr[8],int arr1[8],int arr2[8],int position){
	int i;
	for (i = 0; i < 8; ++i){  //遍历数组将元素按第position位为0和1分为两组
		if (arr[i] & (1 << position) == 1){  //若元素第position位为1
			arr1[i] = arr[i];  //将元素放入数组arr1
		}
		else{  //若元素第position位为1
			arr2[i] = arr[i];  //将元素放入数组arr2
		}
	}

}

//主函数
int main(){
	int arr[8] = { 1, 2, 3, 5, 3, 2, 1, 6 };
	int arr1[8] = { 0 };
	int arr2[8] = { 0 };
	int len;  //用以保存数组arr的长度
	int num;  //用以保存两个只出现一次的数的异或结果
	int position;  //用以保存一个数的最低且为1的二进制位的位数
	len = sizeof(arr) / sizeof(arr[0]);  //计算数组arr的长度
	num = first_occur_number(arr,len);  //调用找找一个出现一次的数函数
    position = find_min1_bit(num);  //调用找一个数的最低且为1的二进制位函数
	divide_array_by_bit(arr, arr1, arr2, position);  //调用利用二进制位分解数组函数
	int number1 = first_occur_number(arr1, len);  //调用找找一个出现一次的数函数
	int number2 = first_occur_number(arr2, len);  //调用找找一个出现一次的数函数
	printf("%d %d\n", number1, number2);  //打印输出结果
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值