找出只出现一次的两个数字,其余数字出现2次,

找出只出现一次的两个数字,其余数字出现2次,

思路:
第一步:利用分治的思想先将两个出现一次的数字找出来,
第二步:然后将整体分解成某一位是0和1的两组数字,
第三步:然后在分别进行异或就可以了

具体过程如下:

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

void FindTwoNum(int arr[], int size, int* num1, int* num2){
	//首先找到数组中出现一次的两个数
	int ret = 0;
	for (int i = 0; i < size; i++){
		ret ^= arr[i];
	}

	//找到一个为1 的二进制位
	int pos = 0;//pos 位置就是二进制位1 的位置
	for (int pos = 0; pos < 32; pos++){
		if ((ret &(1 << pos)) != 0){
			break;
		}
	}

	*num1 = 0;
	*num2 = 0;
	for (int i = 0; i < size; i++){
		if (arr[i] & (1<<pos) == 1) {
			//根据pos位置分为1
			*num1 ^= arr[i];
		}
		else {
			//根据pos位置分为0
			*num2 ^= arr[i];
		}
	}
}
int main(){
	int num1 = 0;
	int num2 = 0;
	int arr[] = { 1, 1, 2, 3, 2, 4 };
	//int size = sizeof(arr) / sizeof(arr[0]);
	FindTwoNum(arr, 6, &num1, &num2);
	printf("两个数字分别是: num1=%d num2=%d\n", num1, num2);
	system("pause");
	return 0;

}

**运行结果: **
在这里插入图片描述

c++, 先找出只出现一次的两个数的异或值, 再将原数组分成两组(通过一个为1的标志位来决定),分别找出只出现一次的数(再异或一次)

class Solution {
public:
	vector<int> singleNumber(vector<int>& nums) {
		//第一步:先找到只出现一次的两个数
		int ret = 0;
		for (int i = 0; i < nums.size(); i++) {
			ret ^= nums[i];
		}
		//第二步: 找到标志位为1的位置,用来区分最后一位是0(将这类数分一组)和最后一位是1(这一组的最后一位都是1)
		ret &= (~ret) + 1;
		int nums1 = 0;
		int nums2 = 0;
		//第三步: 遍历循环 ,分成两组之后,然后再各自进行异或处理
		for (int i = 0; i < nums.size(); i++) {
			if ((ret & nums[i]) == 1) { //这里有坑!记得一定要用括号把&括上:(ret & nums[i]),然后再==啊!
				nums1 ^= nums[i];
			}
			else {
				nums2 ^= nums[i];
			}
		}
		return{ nums1, nums2 };
	}
};
第一步:
把所有的元素进行异或操作,最终得到一个异或值。因为是不同的两个数字,所以这个值必定不为0for (int i=0;i<nums.size();i++ ) {
             ret ^= nums[i];
           }
第二步:
取异或值最后一个二进制位为1的数字作为ret,如果是1则表示两个数字在这一位上不同。
ret &= (~ret)+1;
第三步:
通过与这个ret进行与操作,如果为0的分为一个数组,为1的分为另一个数组。这样就把问题降低成了:“有一个数组每个数字都出现两次,有一个数字只出现了一次,求出该数字”。对这两个子问题分别进行全异或就可以得到两个解。也就是最终的数组了。
 for (int i=0;i<nums.size();i++ ) {
          if ((ret & nums[i]) == 0 ) {
              nums1 ^= nums[i];
           } else {
               nums2 ^= nums[i];
           }
          }
          return {nums1,nums2};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值