Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
感謝cnblog博主feiling,這篇博客一方面參考了feiling的博客,也加入了自己的一些看法。
[解題思路]
要求線性時間復雜度,同時空間復雜度為O(1),即只允許開常數個空間。
最直接的思路是對每一個元素嘗試查找是否有重,如果沒有重,就返回。
class Solution { public: int singleNumber(int A[], int n) { // IMPORTANT: Please reset any member data you declared, as // the same Solution instance will be reused for each test case. int i = 0, j = 0; int ans = 0; for(i = 0;i < n;i++) { for(j = 0;j < n;j++) { if(i == j) continue; else if(A[i] == A[j]) break; else continue; } if(j == n) return A[i]; } } };
不幸的是雖然是o(n2)的時間復雜度,但是還是超時了。於是乎就得想一個o(n)的算法。
o(n)的算法只能是線性掃描一遍,可能的相法是位運算。對於異或來說:
1. 異或運算是可交換,即 a ^ b = b ^ a
2. 0 ^ a = a
那么如果對所有元素做異或運算,其結果為那個出現一次的元素,理解是a1 ^ a2 ^ ....,可以將所有相同元素交換至相鄰位置,首先運算相同元素,則會產生(n - 1)/2個0異或積,剩余一個單一元素,他們的異或積為這個單一元素自己,得解。
1 public class Solution { 2 public int singleNumber(int[] A) { 3 // Note: The Solution object is instantiated only once and is reused by each test case. 4 if(A == null || A.length == 0){ 5 return 0; 6 } 7 int result = A[0]; 8 9 for(int i = 1; i < A.length; i++){ 10 result = result ^ A[i]; 11 } 12 return result; 13 } 14 }
本題擴展
1.一個數組中有兩個元素只出現一次,其他所有元素都出現兩次,求這兩個只出現一次的元素
[解題思路]
將數組所有元素都進行異或得到一個不為0的結果,根據這個結果中的不為0的某一位將數組分成兩組
將兩組中的元素進行異或,如兩個數組的異或值都不為0,則得到最后結果
2.一個數組中有一個元素只出現1次,其他所有元素都出現k次,求這個只出現1次的元素
[解題思路]
當k為偶數時,同lss
當k為奇數時,將數組中每個元素的每一位相加mod k,得到結果即位出現1次的元素,時間復雜度O(nlen),空間復雜度為O(1)