版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hanani_Jia/article/details/82632674
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字
之前遇到过类似的题,不过当时的题目是整型数组中除了一个数字外,其他都出现了偶数次,找出那个只出现一次的,那个就很简单了,这时候就能想到我们的异或运算符,异或是一个位运算符,他会对比两个数字的二进制数,相同位置符号相同为0不同为1。所以如果我们一个数字中除了某一个数字外,其他的数字都出现了两次,相同的数字异或的时候他们的每一位都是相同的所以结果为0,两个两个抵消掉,整个数组不停的去异或得到的就是我们想要的那个出现一次的数字
public static int find1From2(int[] a){
int len = a.length, res = 0;
for (int i = 0; i < len; i++){
res = res ^ a[i];
}
return res;
}
但是这次不同,这次我们是有两个数字是出现一次的,所以如果你再去异或的话得到的结果就是两个数字异或的结果。这里先不说如何简单的去求解,先说一下暴力求解,这里我用了两个for循环来一个数字一个数字的对比。
class Solution {
public:
void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) {
int i = 0;
int j = 0;
int flag = 0;
int flag1 = 0;
int length = data.size();
for (i = 0; i < length; i++)
{
for (j = 0; j < length; j++)
{
flag = 0;
if (j == i)
{
continue;
}
if (data[i] == data[j])
{
flag = 1;
break;
}
}
if (flag == 0)
{
if (flag1 == 0)
{
*num1 = data[i];
flag1 = 1;
}
else
{
*num2 = data[i];
}
}
}
return ;
}
};
这里我定义了两个标志符号,一个是来标记这个数字在数组里边有没有相同的数字,另一个来标记得到的这个出现一次的数字是给了num1还是给num2,这个程序应该不难理解。
下边我们说一下通过异或来解决的方法:
我们上边也说了如果是一个数组里边除了一个数字其他都出现了偶数个那我们解决起来是很简单的,但是我们现在有两个单独的数字,这里我们就像能不能有一种方法去把我们的这整个数组给分开,把这两个数字放到不同的数组里边,并且除去他们两个之外相同的数字也要在同一个数组里边,这不就把我们现在这个问题转换成了刚刚我们所说的我们能够实现的问题。
但是这里要怎么分才是难点,不能说像我刚刚一样O(n2)去对比这样都能求出来了就没必要分开了。
class Solution {
public:
void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) {
int len = data.size();
int ret = 0;
int count = 0;
int i = 0;
for (i = 0; i < len; i++)
{
ret = ret^data[i];
}
for (count = 0; count < 32; count++)
{
if ((ret & 1))
{
break;
}
else
ret = ret >> 1;
}
*num1 = 0;
*num2 = 0;
for (i = 0; i < len; i++)
{
if (((data[i]>>count)&1))
{
*num1 ^= data[i];
}
else
{
*num2 ^= data[i];
}
}
}
};
修改了很久的代码,总是有各种小错误。最后也不知道咋莫名其妙的通过的测试。这里我们简单说一下,我们先让数组中所有数据进行异或,这样得到的结果就是我们那两个数字的异或,既然是异或那就是如果异或得到的数字中某一位是1那就说明这两个数字对应的位置的数是不同的,既然是不同的那我们就能把他俩区分开,至于哪个是1哪个是0根本不重要我重要的是把他们两个区分开。
for (count = 0; count < 32; count++)
{
if ((ret & 1))
{
break;
}
else
ret = ret >> 1;
}
这里我们就是在找这两个数字里边哪一位不同,随便找一位就可以啊,所以我们开始让他右移然后和1进行与运算如果运算结果是1那就说明当前这个位置是1,,找到后退出循环,也就是说这两个不同的数字的第count位是不同的。
for (i = 0; i < len; i++)
{
if (((data[i]>>count)&1))
{
*num1 ^= data[i];
}
else
{
*num2 ^= data[i];
}
}
然后把数组中第count位是1的在一组和num1异或,count是0的在另一组和num2异或,就可以了,哪有人有疑问,其他的数据是怎么分开的,那我还是这个标准,你相同的数组在count位肯定都是0或者都是1,自然肯定就在一组了,至于那边数据多那边数据少不影响啊,肯能num2这里只有一个那个单独的数据,但是不影响结果。
今天给大家分享一个简单的选择题
如有定义:char str[20];,能将从键盘输入的字符串“How are you”保存到 str 数组的语句是( )
A.scanf("%s", str);
B.str[] = getch();
C.gets(str);
D.str = gets();