目录
前言
小伙伴们大家好!今天 up 主为大家带来的是程序员必刷题之剑指offer中的一道比较简单,但同时又是很重要的一道题:数组中数字出现的次数。
题目
力扣上题目描述如下所示:
好的,那么如上题所描述的一样,该数组中除了两个数字只出现了一次,其他数全部都出现了两次。那么我们就可以理解题目所说的了。
其次,该题目要求了时间复杂度以及空间复杂度,所以我们必须得在一定的范围内去做。
思路
第一步
我们知道,有一种操作符叫做异或操作符,它的特性是两元素异或时,二进制位相同为0,不同为 1。因为这个数组的特性就是除了两个单独出现的元素之外,其他元素都是成对出现的。如果我们将该数组中所有元素全部异或到一起,那么得到的便是两个单独的元素的异或值。
第二步
因为该异或值最后的结果是两个不同的元素,那么就说明两个不同的数的二进制位一定有一位是不相等的,所以,我们需要找出这个不相等的二进制位的位置 pos 。代码如下所示:
第三步
当我们找到了这个二进制位之后,我们会将该整个数组分为两部分。第一部分是 pos 位置为 0 的数,第二部分是 pos 位置为 1 的数,然后将这两组数分别异或在一起,最后得到的便是两个单独出现的数,将其放入数组中即可。
代码实现
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* singleNumbers(int* nums, int numsSize, int* returnSize){
int* arr = (int*)malloc(2*sizeof(int));
*returnSize=2;
int i=0;
int tmp=0;
//
for(i=0;i<numsSize;i++)
{
tmp^=nums[i];
}
int pos=0;
while((tmp&1)==0)
{
tmp=tmp>>1;
pos++;
}
arr[0]=0;
arr[1]=0;
for(i=0;i<numsSize;i++)
{
if(((nums[i]>>pos) &1)==1)
arr[0]^=nums[i];
else
arr[1]^=nums[i];
}
return arr;
}
对于上述原码,可能一些小伙伴会有疑问,为什么这里动态内存开辟了两个空间,然后前面会将*returnSize 赋值为 2,明明原先的数组可以存放的下。
其实这里是因为力扣上需要我们这样去做,然后平台才能审核代码。也就是需要一个规范。因为该函数在接收我们的返回值值时,是用 returnSize 接收的,所以这里必须要将 *returnSize 的值赋为 2.用以接收传递的 arr 数组。
好的,那么本为到此就结束啦!如有问题,还请指正呀!