LeetCode系列记录我学习算法的过程。
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
题目
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例:
输入: [2,2,1]
输出: 1
输入: [4,1,2,1,2]
输出: 4
思路
这个题目看起来很简单,只需要找到只出现过一次的数字即可
那我们可以遍历整个数组,然后将每个数字出现的次数记录下来,找到次数为 1 的即可:
- 首先定义
map存储所有数字及出现的次数 - 遍历传入的数组
- 当遍历项在
map中有记录时,将次数加1 - 无记录则设置次数为
1 - 最后遍历
map,将出现次数为1的数字返回即可
代码实现
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
// 存储所有数字出现的次数
const map = new Map()
// 遍历传入的数组
nums.forEach(n => {
// 如果有记录,则将其出现次数加 1
if (map.has(n)) {
map.set(n, map.get(n) + 1)
} else {
// 无记录则设置次数为 1
map.set(n, 1)
}
})
// 遍历所有记录
for(let [key, value] of map) {
// 如果当前遍历项值为1,返回key
if(value === 1) return key
}
};
优化
没仔细审题,题目还有一个提示就是除了只出现一次的数字,其他数字都只出现两次,这个其实是一个很好的切入点,可以用到位运算中的异或( ^ )
异或( ^ ):
- 一个数和
0做 异或 运算等于本身 - 一个数和其本身做 异或 运算等于
0
故而在以上的基础条件上,将所有数字按照顺序做异或运算,最后剩下的结果即为只出现一次的数字
这样实现下来的话 时间复杂度:O(n),空间复杂度:O(1):
var singleNumber = function(nums) {
// 存储最后的答案
let ans = 0
// 遍历传入的数字
for(const num of nums) {
// 进行 异或 操作
ans ^= num
}
// 返回结果
return ans
};