寻找单身狗

单身狗1.

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/single-number

int singleNumber(int* nums, int numsSize)
{
	int ret = 0;
	for (int i = 0; i < numsSize; i++)
	{
		ret ^= *(nums + i);
	}
	return ret;
}

这题的解题思路是异或,题目要求时间复杂度为线性,在异或的解法中,只遍历了一遍数组,时间复杂度就是O(N),而空间开辟只有一个变量,即空间复杂度是一个常量,即O(1),满足题目要求。

我们知道异或操作符,在这期内容中,异或是重点讲解的对象,这里简单讲述一下异或的作用:

int main()
{
    int m = 10;
    int n = 15;
    int k = m ^ n;
    return 0;
}

上面代码中k是m和n异或的结果,那么k最终的值是多少呢?

10 -- 1010
15 -- 1111

^的作用是两个数二进制中将两者进行每位二进制位比对,而比对的结果是相同为0,相异为1,因此上述代码中k的最终值为0101,转换为十进制就是3。由于^符号的特殊性,在这里还可以引申出一个用法:

int a = 10 ^ 10;

由于相同为0相异为1,因此两个相同的数相互异或结果就为0,上式a的最终值为0。

那么就是关于本体的思路了,说了这么多,想必看到这里思路已经很清晰了,在遍历数组的时候,每个数字经历了两次遍历那就直接使得最终值ret = 0了,而最后那个没有参与相互异或的那个数就会是ret值的最终值。


单身狗2.

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/single-number-iii

与上题不同的是,这一次数组中出现了两只单身狗,如果像上一题直接异或,最后的结果是两个单身狗相互异或的值,相比之下难度多了不少。

这题可以采取的思路是,将两个单身狗分到两组,然后再进行异或,然后分别保存到数组里,那不就又行了吗,那么如何将两个单身狗分到两个数组之中呢?

我们知道异或整个数组的结果是两个单身狗相互异或的结果,那么是不是可以通过这个结果来实现两个单身狗的分组呢?

15 -- 1111
13 -- 1101
13^15 0010

假设数组中单身狗分别为15和13,其异或的结果是2,那根据这个异或的结果,可以将数组分类为二进制位第二位不相同的两组数据,分完之后就可以对数组异或直接得到两个单身狗了。

上代码:

int* singleNumber(int* nums, int numsSize, int* returnSize)
{
    *returnSize = 2;
	int* ret = (int*)calloc(sizeof(int), *returnSize);
	if (ret == NULL)
	{
		perror("calloc");
		return NULL;
	}
	//分组
	int tmp = 0;
	int i = 0;
	for (i = 0; i < numsSize; i++)
	{
		tmp ^= *(nums + i);
	}
	i = 0;
	while ((tmp & 1) != 1)
	{
		tmp = tmp >> 1;
        i++;
	}
	for (int j = 0; j < numsSize; j++)
	{
		if ((*(nums + j) >> i) & 1)
		{
			ret[0] ^= *(nums + j);
		}
		else
		{
			ret[1] ^= *(nums + j);
		}
	}
	return ret;
}

本期的题解分享就到处为止了,喜欢的关注点点关注哦。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值