1. 若只有一个数出现一次,则使用下文 SPECIAL函数就可解决。思路:因为相同的两个数按位异或为0,所以一组数顺次异或之后得到的那个数就是所求。


2. 若有两个数。思路:将这两个数分到两个组,分别找这两个组中的特殊值。具体分组规则:将原先一组数字全部异或之后所得到的是那两个特殊数字的异或值,二进制位一定存在“1”,找到从右向左的第一个位置的“1”记为count(如果从右向左第二位是1,则是2,若第三位是1,则是4),然后以count将这两个数字分到两组,当然是对原先的一组数与count进行按位与&运算,结果为1分到一个组,结果是0分到另一个组中,这样就可将一组数字分到两个组中,当然一组数字和count按位与之后,结果1还是0不确定,所以出现只有一个数字在一个组中的情况也是存在的,但我们这里的目的是将两个特殊数字分开,如此而已,这样就达到我们的目的了。



#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


int SPECIAL(int *str, const int num)//从一组只有一个数字单个出现,其他数字成对出现的数中,找出那个孤零零的数字
{
 assert(str);  //断言判断指针是否为空
 int i = 0;
 int count = 0;
 while (i++ < num)
 {
  count ^= *str++;   //异或之后就可得到出现一次的那个数字
 }
 return count;
}

int find_one(const int num)  //找count二进制数中从右到左首先出现的“1”
{
 int count = 1;
 while (count)
 {
  if (count == (count&num))
   break;
  count = count << 1;
 }
 return count;
}

#define size 10
#define ran 0xcccccccc  //数组初始化ran

int no_ran(int *str)  //
{
 assert(str);
 int count = 0;
 while (*(str++)!=ran)
 {
  count++;
 }
 return count;
}


int main()
{
 int string[size] = { 0,2,3,4,5,0,2,3,7,4 };//原数组不能包含ran的值
 int str1[size] = { ran }, str2[size] = { ran };////数组初始化ran=0xcccccccc
 int count1 = 0, count2 = 0;    //
 int special_1 = 0, special_2 = 0;   //那两个单个的数字
 int i = 0, j = 0, k = 0;
 count1 = SPECIAL(string, size);
 //找count二进制数中从右到左首先出现的“1”
 count2 = find_one(count1);
 //将string数组分为两组 str1 ,str2,并且 前面为数字后面为0
 for (i = 0, j = 0, k = 0; i < size; i++)
 {
  if (count2 == (string[i] & count2))
   str1[j++] = string[i];
  else
   str2[k++] = string[i];
 }
 printf("原数组为:\n");
 for (i = 0; i < size; i++)
  printf("%d ", string[i]);
 printf("\n数组 str1 为:\n");
 for (i = 0; i < size; i++)
  printf("%d ", str1[i]);
 printf("\n数组 str2 为:\n");
 for (i = 0; i < size; i++)
  printf("%d ", str2[i]);
 //输出两个特殊的数字
 printf("\n\nspecial_1 = %d\n", SPECIAL(str1, no_ran(str1)));
 printf("special_2 = %d\n", SPECIAL(str2, no_ran(str2)));
 system("pause");
 return 0;
}

//************************************************************************//

//对上述程序修改简化之后//

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

int SPECIAL(int *str, const int num)//从一组只有一个数字单个出现,其他数字成对出现的数中,找出那个孤零零的数字
{
 assert(str);  //断言判断指针是否为空
 int i = 0;
 int count = 0;
 while (i++ < num)
 {
  count ^= *str++;   //异或之后就可得到出现一次的那个数字
 }
 return count;
}

int find_one(const int num)  //找count二进制数中从右到左首先出现的“1”
{
 int count = 1;
 while (count)
 {
  if (count == (count&num))
   break;
  count = count << 1;
 }
 return count;
}

#define size 10


int main()
{
 int string[size] = { 0,2,3,4,5,0,2,3,7,4 };
 int count1 = 0, count2 = 0;    //
 int special_1 = 0, special_2 = 0;   //那两个单个的数字
 int i = 0;
 count1 = SPECIAL(string, size);
 //找count二进制数中从右到左首先出现的“1”
 count2 = find_one(count1);
 //将string数组分为两组后分别异或得到两组中的特殊值
 for (i = 0; i < size; i++)
 {
  if (count2 == (string[i] & count2))
   special_1 ^= string[i];
  else
   special_2 ^= string[i];
 }
 printf("原数组为:\n");
 for (i = 0; i < size; i++)
  printf("%d ", string[i]);
 printf("\nspecial_1 = %d\nspecial_1 = %d\n", special_1, special_2);
 system("pause");
 return 0;
}

笔试面试成对出现的一组数,只有一个或两个只出现一次的数字,找到它们。_C/C++

笔试面试成对出现的一组数,只有一个或两个只出现一次的数字,找到它们。_面试_02