問題定義:有2n+1個數,只有一個單着,別的都是成對的,找出這個單着的數。比如:2 1 3 2 1。3是答案。
思路一:暴力搜索——每個數都和其他數比較,找不到相同的,就得到了結果。時間復雜度為o(n2)
思路二:排序搜索——先給序列排個序,之后從前往后一對一對的找,直到不是成對的為止。時間復雜度,怎么也得o(nlgn)
思路三:異或計算,一趟搞定。時間復雜度o(n)
直接看思路三:
原理:異或操作(^)——(對於位操作)相同為0,相異為1.比如:1^0 = 1, 1 ^1=0
這樣:
- 兩個相同的數異或就為0
- 任何數和0異或為自己(轉化到位。1^0 = 1, 0 ^0=0)
例如:5 ^ 5 = 0
5 ^ 0 = 5
對於本題:2 1 3 2 1,都異或一下:相同的(2^2,1^1) 為0,剩下的3和0異或為自身3。(注:異或具有交換律)
參考代碼:
#include <stdio.h> int main() { int a[5] = {2, 1, 3, 2, 1}; int aim = a[0]; for(i = 1; i < 5; i++) { aim = aim ^ a[i]; } printf("Result:", aim); return 0; }
異或在這方面挺好,再來個應用:
不用第三個數直接交換兩個數:
#include <stdio.h> void swap(int *a, int *b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } int main() { int a=3, b=5; swap(&a, &b); printf("%d\n%d", a, b); return 0; }
當然完成這個題目還可以用同樣的思維:
#include <stdio.h> void swap(int *a, int *b) { *a = *a + *b; *b = *a - *b; *a = *a - *b; } int main() { int a=3, b=5; swap(&a, &b); printf("%d\n%d", a, b); return 0; }