稀土掘金刷题-找单独的数

74 阅读3分钟

问题描述

有一堆数字,除了一个数字,其它的数字都是成对出现。班上的每个同学拿一个数字,正好将这些数字全部拿完,问如何快速找到拿了单独数字的同学?

[测试用例] `int main() { // Add your test cases here

int test1[] = {1, 1, 2, 2, 3, 3, 4, 5, 5};
int test2[] = {0, 1, 0, 1, 2};

printf("%d\n", solution(test1, 9)==4 );
printf("%d\n", solution(test2, 5)==2);

return 0;

}`

以下是我开始写的代码 `int solution(int inp[], int size) { int i=0; while(i<size) { if(inp[i-1]!=inp[i+1]&&inp[i-1]!=inp[i]&&inp[i+1]!=inp[i]) { return inp[i]; } i++; } // Edit your code here

}`

最开始忽略了越界的问题,当i==0时i-1会越界,当i==size时i+1会越界。后来想到可以通过[运算符]^解决, 具体思路 1. 首先明确问题的关键在于找出那个唯一不成对出现的数字。由于其他数字都是成对的,所以如果对所有数字进行某种运算,能够消除成对数字的影响,那么最后剩下的就是那个单独的数字。 2. 考虑到异或运算的性质,对给定的数字列表中的所有数字依次进行异或操作。

  • 当遇到第一个数字时,初始结果为 0,与这个数字异或后结果为这个数字本身。

  • 当遇到第二个相同的数字时,由于异或运算的性质,结果又变回 0。

  • 对于成对出现的数字,经过异或运算后都被消除了影响。

  • 而那个单独的数字,因为没有与之相同的数字进行异或,所以最终会保留在结果中。 3. 这样,遍历完整个数字列表后,得到的结果就是那个拿了单独数字的同学手中的数字。 即 `int solution(int inp[], int size) { int i=0; int result=0; while(i<size) { result ^= inp[i]; // 使用异或操作

      i++;
    

    } // Edit your code here return result;`

^即异或运算符,它的用法如下: 定义一个整型的result,与数组的每一位进行异或操作,result 变量在每次循环中进行异或操作的作用是利用异或运算的性质来找到数组中单独出现的那个数字。

异或运算具有以下重要性质:

  1. 任何数与自身异或结果为 0。例如, a ^ a = 0 。
  2. 0 与任何数异或结果为那个数本身。例如, 0 ^ a = a 。

在这个问题中,数组中除了一个数字单独出现外,其他数字都是成对出现的。当对数组中的所有数字进行异或操作时:

  • 成对出现的数字在异或过程中会相互抵消,结果为 0。因为对于每一对相同的数字 a 和 a ,它们异或的结果是 0。
  • 而那个单独出现的数字与 0 异或,最终结果就是那个单独的数字本身。

所以通过不断地对数组中的数字进行异或操作, result 最终会存储那个单独出现的数字。