「leetcode」136.只出現一次的數字

原題

給定一個非空整數數組,除了某個元素只出現一次之外,其他每一個元素均出現兩次。找出那個只出現了一次的元素。算法

說明:數組

你的算法應該具備線性時間複雜度。 你能夠不使用額外空間來實現嗎?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循環

  1. 兩個相同的數進行按位異或等於0
  2. 任意一個數與0進行按位異或等於自身
// 0
100 ^ 100
// 0
-99 ^ -99

// 100
100 ^ 0
// -2
0 ^ -2
複製代碼

代碼

解法1:利用hash

/** * @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
};
複製代碼

解法2: 利用異或

沒錯,就是這麼簡單😂

/** * @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
};
複製代碼

🤔️ 爲何能夠這樣?原題中說給定一個非空整數數組,除了某個元素只出現一次之外,其他每一個元素均出現兩次。找出那個只出現了一次的元素。, 因而咱們能夠將代碼執行的過程分解成下面的過程

  1. nums = [a, b, a, c, b, c, d]

  2. result = a ^ b ^ a ^ c ^ b ^ c ^ d

  3. result = (a ^ a) ^ (b ^ b) ^ (c ^ c) ^ d

  4. result = 0 ^ 0 ^ 0 ^ d

  5. result = d 獲得了只出現了一次的數字

相關文章
相關標籤/搜索