LeetCode 260 只出现一次的数字(超详细)
Posted S for N
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 260 只出现一次的数字(超详细)相关的知识,希望对你有一定的参考价值。
LeetCode 260 只出现一次的数字
题目简述
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按任意顺序返回答案。
进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
思路讲解
这道题其实是另一道题的进阶版本,如果此题问的是给定一个整数数组 nums,
其中恰好有一个元素只出现一次,其余所有元素均出现两次。
找出只出现一次的那个元素,这个时候我们就可以将整个数组异或,得出来的就是那个数。
而现在有两个只出现一次的数,那么我们整体异或出来的数就是这两个数异或的结果
(如果有对异或不太了解的可以先去下面看一看,下面有介绍异或)。
那么我们想做出这题,有两个思路,
一个是将这两个数异或出来的结果分解出原来的两个数,而这种思路很难实现。
而另一种思路是将这个题变成之前的那种只有一个出现一次的情况,
将这两个数分别分出来,相当于把原来的这个数组分成两组,每组都只有这一个是只出现一次的,
然后将这两组数据分别异或,这样就能分别出来这两个数。因为返回顺序是任意的,因此只要返回这两个数就行。
按代码片段分别讲解
//下面是思路的第一步,先将所有的数据都异或
//先将所有的数据都异或
int i = 0;
int ret = 0;
for (i = 0;i < numsSize;i++)
{
ret ^= nums[i];
}
// 然后就是分组了,那么我们将异或完的数据的二进制的各个位与1异或找出哪一位是1
//看异或的结果的哪一位是1
int m = 0;
while (((ret >> m) & 1) != 1)
{
m++;
}
那么我们为什么要找出哪一位是1呢?
因为这两个数只出现一次,就代表着他们俩异或出来的结果肯定有一位是1
而我们找出这一位有什么作用呢?
按照我们的思路,我们需要将这两个数分别分到两组去,而除了这两个数之外的数字均出现了两次,
那么我们只需要根据这一位是1的和不是1的进行分组,
那么不光这两个出现一次的分到了不同的组里,每个组里的其他数字肯定也都是出现两次的。
//将m位是1的都异或到一起
//将m位是0的都异或到一起
//将m位是1的都异或到一起
//将m位是0的都异或到一起
int x1 = 0;
int x2 = 0;
for (i = 0;i < numsSize;i++)
{
if ((nums[i] >> m) & 1)
{
x1 ^= nums[i];
}
else
{
x2 ^= nums[i];
}
}
完整解答
下面来看一下完整的解答
int* singleNumber(int* nums, int numsSize, int* returnSize)
{
//先将所有的数据都异或
int i = 0;
int ret = 0;
for (i = 0;i < numsSize;i++)
{
ret ^= nums[i];
}
//看异或的结果的哪一位是1
int m = 0;
while (((ret >> m) & 1) != 1)
{
m++;
}
//将m位是1的都异或到一起
//将m位是0的都异或到一起
int x1 = 0;
int x2 = 0;
for (i = 0;i < numsSize;i++)
{
if ((nums[i] >> m) & 1)
{
x1 ^= nums[i];
}
else
{
x2 ^= nums[i];
}
}
int* RetArr = (int*)malloc(sizeof(int) * 2);
RetArr[0] = x1;
RetArr[1] = x2;
*returnSize = 2;
return RetArr;
}
如果还有哪里不清楚的可以给我留言。
以上是关于LeetCode 260 只出现一次的数字(超详细)的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode Java刷题笔记—260. 只出现一次的数字 III
260. 只出现一次的数字 III 的 两种解法(详细复习位运算解法)