题集-单身狗问题

文章介绍了一种使用异或操作解决数组中只出现一次的两个数字的问题。通过异或所有数组元素找到不同位,然后根据该位对数组进行分组,从而找出两个单独的数字。针对可能出现负数的情况,文章改用了右移操作来确定二进制位数,使得解决方案更加通用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

编写一个函数找出这两个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6.

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>

int team(int n, int count)//判断分组根据的是哪一位
{
	while (count--)
	{
		n %= 2;
	}
	return n.
}
int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
	int len = sizeof(arr) / sizeof(*arr);
	int fru = 0;
	int s1 = 0;
	int s2 = 0;
	for (int i = 0; i < len; i++)
	{
		//将所有的数字异或在一起,这时的结果就是两个单独数字的异或结果
		//这个结果中的为1的位就是两个数字不同的一位
		//按照这个位进行分组,将数组分成两组,这时的两个数字就会被分到两组
		//分组后进行组内异或就会找到这两个单独的数字
		fru ^= arr[i];
	}
	int count = 1;//记录位数
	while (fru%2 !=1)
	{
		count++;
		fru /= 2;
	}
	for (int i = 0; i < len; i++)
	{
		if (team(arr[i], count) == 1)
		{
			s1 ^= arr[i];
		}
		else s2 ^= arr[i];
	}
	printf("%d %d\n", s1, s2);
	return 0;
}

以上是一种单身狗问题的解决思路,下面我们针对leetcode上的问题进行改进

首先,以上的方法中,对于二进制中的位数的求法采用的是除以2的方式,这种方法不适用于数据中有负数的样例:

260. 只出现一次的数字 III - 力扣(LeetCode)

所以,我们将二进制位数问题用右移方式完成。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 int team(int n,int count)
 {
     return (n >> count)&1 ;
 }
int* singleNumber(int* nums, int numsSize, int* returnSize){
    int t  = 0;
    int *ret = (int *)calloc(2,sizeof(int));
     for(int i = 0; i < numsSize; i ++)
     {
         t ^= nums[i];
     }
     int count = 0;
     for(int i = 0; i < 32; i ++)
     {
         if((t >> i)&1 == 1)
         {
         count = i;
         break;
         }
         
     }
     for(int i = 0; i < numsSize; i ++)
     {
         if(team(nums[i],count) == 1)
         {
             ret[0] ^= nums[i];
         }
         else if(team(nums[i],count) == 0)
         {
             ret[1] ^= nums[i];
         }
     }
     *returnSize = 2;
     return ret;
}

这样就可以适用于含有负数的样例了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值