这次写的博客很简单就是想分享一下写力扣题的一些思路,希望能对需要的人有点帮助呀。那么就让我们先来看看题目的要求(这是一道OJ题,只需要完成函数就行了)
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
在这里我先放一下我写的代码然后再去解释思路:
int* singleNumbers(int* nums, int numsSize, int* returnSize)
{
int count1 = nums[0], count2 = 0, count3 = 0;
int i = 0;
for (i = 1; i>(count3-1))&1 == 1)
{
//如果有符合条件的那么就直接和count2异或
count2 ^= nums[i];
}
}
int* ptr = (int*)malloc(2 * 4);
*ptr = count2;
count1 ^= count2;
*(ptr + 1) = count1;
*returnSize =2;
return ptr;
}
那让我来解释下这段代码以及我做这题时的思路:当我们看到一个题目的时候有几件事情我感觉需要去做一下,首先看一下题目让我们干什么这是第一步需要我们去做的事情,然后就是去分析他给的这个函数的参数,OJ题的函数参数是干什么的不会在题目中明确告知,我们需要根据参数名来去分析我认为分析函数的参数是十分重要的,我就是因为一开始做这题的时候没有分析清楚出的错。就例如这一题它刚进入的时候给的函数以及参数就是:
int* singleNumbers(int* nums, int numsSize, int* returnSize){
}
分析完了函数的参数,我们就需要开始对题目进行分析了,说到这里我们就再顺便一提,写这种编程题其实我感觉提前想好思路画好图,再根据思路去写代码,比看到题目就直接敲代码,想到哪是哪的那种做法要好不少,因为事先想好思路在编的时候会很丝滑,而且也方便出错后的检查。
那我们开始分析这个题目:首先题目说数组里面只有两个数是单身数,其他的数都是重复存在的,看到这里就想要怎么做才能够把重复的全去掉,只留下单身的数,或者只留下与单身的数有关的数,这时候就要想到一个位操作符异或(^)操作符,它就是两个数字的二进制位依次异或:同为0,异为1,知道这个性质之后,是不是就可以把数组里面的所有元素异或一下,这样得到的是不是就是两个单身的数异或的结果。得到这个结果之后我们要想的就是如何的到这两个数了?那我们就可以从这个异或之后的这个数做文章。
我们知道异或是同为0异为1,那么是不是异或之后的count1它的二进制中为1的那些位,两个单身的对应位上的数是不相同的,也就是说我们可以根据这一点来区分出来这俩个数,之后就有了两种做法:第一种是根据这点不同可以将两个数分到两个数组中去,然后每个数组中的元素进行异或,就可以分别得到这两个数(但是这样有一点不好就是需要创建新的数组,需要开辟新的空间,效率不是很高),在这里我选择的是第二种,不需要去开辟空间直接在原来的上面去改动。
下面我就来详细的说一下第二个思路:我用图来表示好说一点(用手绘板写的字有点丑请见谅)
上图就是第二种方法的思路,剩下的就是去实现这个思路了,可以参考这个代码,这个OJ题调用后会自己free并且把malloc或者calloc置空,所以不需要我们手动去置空。
这就是我写这题的思路,希望对大家有所帮助。



