二话不说,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