LeetCode136:只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
解题思路:
这里可以使用异或运算。即两个相同的数字异或为0,而0与任何数字异或都是其本身。把数组所有的数都异或,相同的数字异或是为0,那么剩下的就是那个只出现一次的数字。
代码如下:
int test(vector<int> v)
{
int temp=0;
for(auto& i:v)
{
temp^=i;
}
return temp;
}
LeetCode137:只出现一次的数字-Ⅱ
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。说明:你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗?
解题思路
本题对上述做了一些改进,变成了其余元素出现三次!感觉难了比较多。我们有了第一题的解题思路,可能会先想到也用异或来解决,但是位运算中并没有直接的使得三个相同的数字运算为0的方法!!!
可以遍历所有数,让每个数的二进制的同一位相加,对一个二进制位出现 1的次数对 3取余,若余数为 1,那么我们目标数字的这一位也就是 1.(ps:如果再出个相同数字出现4次的话?方法同理!)
简单的例子,比如
[1,2,2,2] 其转换成二进制就是[01,10,10,10],我们可以知道第一位(从右往左)的二进制总共出现了1次1,那么我们的目标数其二进制在第一位就是1,而相对的第二位出现了3次1,那么我们的目标数的二进制在这一位就不是1。
就这样可以去到得到目标数的二进制的每一位的数字。接着再把其目标数的二进制的每一位的数字进行按位或处理就得得到目标数。
代码如下:
int test(vector<int> v)
{
int reslut=0;
for(int i=0;i<64;++i)//写64个变量(知道范围的写32位应该也行?)记录每位的二进制1出现的次数
{
int t =0;
for(auto& a:v)
{
t+=(a>>i)&1; //得到每个数的二进制同一位为1的次数
}
reslut |=(t%3)<<i;
}
return reslut;
}
思考:得到二进制的每一位的数字,用按位或处理就可以得到目标数。
用个例子来说明:
一个二进制数 1101,我们可以得到其每一位的数字(其他几位没有的,就用0补上)
第一位:0001
第二位:0000;
第三位:0100;
第四位:1000;
把这四个进行按位或处理(有1为1,所有都是0 为0),所以结果是1101。