(No.4)前端写算法之--只出现一次的数字

51 阅读2分钟

二话不说,leetcode HOT100先开干,加油冲冲冲!这次开撕的是--只出现一次的数字。难度:简单

题目:给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

/*  示例1: 
    输入: nums = [2,2,1]
    输出: 1
*/
/*  示例2: 
    输入: nums = [4,1,2,1,2]
    输出: 4
*/
/*  示例3: 
    输入: nums = [1]
    输出: 1
*/

思路:这道题主要考察到异或特性,说实话如果不知道这个知识点的可能想不出来。

异或特性:

  • x^0 = x,任何数和 0 异或都是原来的数
  • x^x = 0,任何数和自身异或都是 0
  • 异或运算满足交换律,a^b^a = a^a^b

答案1:常规解法:

// 这里循环过程中使用对象存储数据,记录数据的出现次数
var singleNumber = function(nums) {
    const len = nums.length
    const obj = {}
    for(let i = 0; i < len; i++){
      if(obj[nums[i]] ){
      // 由于只存在出现1次和出现两次的情况
      // 这里之前出现了一次,那么刚好把前面的删掉
          delete obj[nums[i]]
      }else{
          obj[nums[i]] = 1 // 没出现的就存起来
      }
    }
    return Object.keys(obj)[0] // 最后obj里应只剩一个数据,就是我们要的答案
};// 时间复杂度O(n),空间复杂度O(n)

答案2:基于异或的特性:

var singleNumber = function(nums) {
    let res = nums[0]
    const len = nums.length
    for(let i = 1; i < len; i++){
        res = res^nums[i] // 不断累积各项
    }
    //如:nums=[1,1,2,2,3],可以理解为 1^1^2^2^3 = 0^0^3 = 0^3 = 3
    return res
};// 时间复杂度O(n)

若需要再简化一下,可以使用ES6数组reduce写法:

var singleNumber = function(nums) {
    return nums.reduce((a,b)=>a^b)
};// 时间复杂度O(n)

小Tips

  • Array.reduce(),该方法不会改变原数组,返回值是最终的累加值。方法有两个参数,参数1接收一个函数作为累加器:接受的函数的参数(prev,cur,index,arr),pre: 上一次的结果集,这个值通常会使用 initValue 作为第一次的默认参数,当 initValue 没有传入参数时这个值将会是数组的第一个值。cur: 当前元素。 index: 当前元素的索引 arr: 当前元素所属的数组。参数2为初始值initValue