「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 获得了只出现了一次的数字

相关文章
相关标签/搜索