題目
260. 隻出現一次的數字 III
給定一個整數數組 nums,其中恰好有兩個元素隻出現一次,其餘所有元素均出現兩次。 找出隻出現一次的那兩個元素。你可以按 任意順序 傳回答案。
進階:你的算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實作?
示例 1:
輸入:nums = [1,2,1,3,2,5]
輸出:[3,5]
解釋:[5, 3] 也是有效的答案。
示例 2:
輸入:nums = [-1,0]
輸出:[-1,0]
示例 3:
輸入:nums = [0,1]
輸出:[1,0]
提示:
2 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
除兩個隻出現一次的整數外,nums 中的其他數字都出現兩次
思路
下面兩個原則(重要):
- 任何數字與0異或得到數字本身;兩個相同的數字異或得0。依照這兩個原則,假如一個數組中,有一個元素隻出現一次,其他元素均出現兩次,那麼将數組中所有的數字異或即可得到隻出現一次的元素的結果。
- z & (-z)得到的是z最低位為1的數:例如z為001100,那麼-z:z首先取反110011,然後加1,得到110100,z和-z相與得到100。
接着說下這道題怎麼解:
- 将數組中所有的數進行異或,得到結果z。那麼z中的1位表示的是數組中兩個不同的數字之間不同的位。因為是兩個不同的數,是以一定至少存在一個不同的位。
- 通過z&(-z)取最低位1的數,例如100,結果表示為y。
- y可以将數組分成兩個子數組(規模不一定相同),做法是将y和數組中每個數進行相與,如果為0,則說明與y相與的數,和y最高位的1對應的是0;如果為1,則說明與y相與的數,和y最高位的1對應的是1。上述數組中兩個不相同的數,一定會劃分到不同的子數組中。将子數組中所有的數分别進行異或,兩個子數組最終得到的結果分别就是兩個不同的數。
時間複雜度: O ( N ) O(N) O(N)
空間複雜度: O ( 1 ) O(1) O(1)
class Solution {
public int[] singleNumber(int[] nums) {
int res = 0;
for(int num : nums){
res = res ^ num;
}
res = res & (-res);
int[] arr = new int[2];
for(int num : nums){
if((num & res) == 0) {
arr[0] ^= num;
}else{
arr[1] ^= num;
}
}
return arr;
}
}