給定一個非空整數數組,除了某個元素只出現一次之外,其他每一個元素均出現兩次。找出那個只出現了一次的元素。算法
說明:數組
你的算法應該具備線性時間複雜度。 你能夠不使用額外空間來實現嗎?ui
示例 1:spa
輸入: [2,2,1]
輸出: 1
複製代碼
示例 2:code
輸入: [4,1,2,1,2]
輸出: 4
複製代碼
這道題目最簡單的思路,是利用Hash查詢的時間複雜度爲O(1), 避免使用雙層for循環,致使時間複雜度變爲O(n^2)。可是這不是咱們今天關注的重點。內存
由於,這兩天我一直在看位運算符的相關內容, 其實本題能夠在不使用額外的內存空間,而且是O(n)的時間複雜度下,解答出該題。只須要使用按位異或的操做符^get
按位異或^, 本質上將兩個操做數的二進制數的每一位對齊。而後按以下的規則取值,1 ^ 1 等於 0; 1 ^ 0 等於 1;0 ^ 1 等於1;0 ^ 0等於0。hash
舉一個例子🌰。10和5之間進行按位異或操做的結果15。io
0000 0000 0000 0000 0000 0000 0000 1010
// ^ XOR
0000 0000 0000 0000 0000 0000 0000 0101
// 等於 14=5s
0000 0000 0000 0000 0000 0000 0000 1111
複製代碼
✨除此以外,咱們還須要知道兩個準則:for循環
// 0
100 ^ 100
// 0
-99 ^ -99
// 100
100 ^ 0
// -2
0 ^ -2
複製代碼
/** * @param {number[]} nums * @return {number} */
var singleNumber = function(nums) {
let hashMap = new Map()
let result
for (let i = 0; i < nums.length; i++) {
if (!hashMap.has(nums[i])) {
hashMap.set(nums[i], 1)
} else {
hashMap.set(nums[i], 2)
}
}
for (let i = 0; i < nums.length; i++) {
if (hashMap.get(nums[i]) === 1) {
result = nums[i]
break
}
}
return result
};
複製代碼
沒錯,就是這麼簡單😂
/** * @param {number[]} nums * @return {number} */
var singleNumber = function(nums) {
let result = 0
for (let i = 0; i < nums.length; i++) {
result = nums[i] ^ result
}
return result
};
複製代碼
🤔️ 爲何能夠這樣?原題中說給定一個非空整數數組,除了某個元素只出現一次之外,其他每一個元素均出現兩次。找出那個只出現了一次的元素。
, 因而咱們能夠將代碼執行的過程分解成下面的過程
nums = [a, b, a, c, b, c, d]
result = a ^ b ^ a ^ c ^ b ^ c ^ d
result = (a ^ a) ^ (b ^ b) ^ (c ^ c) ^ d
result = 0 ^ 0 ^ 0 ^ d
result = d 獲得了只出現了一次的數字