这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战
题目描述
给一个数组,都是有值的,整数类型,里面的整数,有一个只出现一次,其它都是出现了两次。现在需要找出那个出现了一次的整数,并且返回它。
举个例子:
arr: [1,2,1]
返回 2
arr: [1,2,3,2,3]
返回 1
arr: [2,2,3,4,3,5,4]
返回 5
思路分析
第一种方法
这个是找出只出现一次的元素,我们可以新建个对象(也可以用Map)做映射
遍历数组,以数组的值做key,1 做value, 每次遍历都要判断对象是否存在该key,如果存在则以 2为value。
最后对对象遍历,找到value等于 1 的key,这个就是只出现一次的数字,返回即可。
代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function (nums) {
const obj = {}
for (let i = 0; i < nums.length; i++) {
if (obj[nums[i]]) obj[nums[i]] = 2
else obj[nums[i]] = 1
}
for (let key in obj) {
if (obj[key] === 1) return key
}
};
这里又有个需求,如果不能利用额外空间,可否实现呢?
答案是可以的。
第二种方法
因为只有一个数字出现1次,其它都出现2次,那么我们对数组进行排序,如果一个数跟它前后都不相等,则证明它只出现一次,对吧?
有个特殊情况,就是首尾需要单独做判断,因为首的话它没有前的元素,尾的话它没有后的元素。
其它情况判断前后元素是否相等就行了。都不相等的话返回即可。
代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function (nums) {
nums.sort((a, b) => a - b)
// 首尾需要特别判断
for (let i = 0; i < nums.length; i++) {
if ((i === 0 && nums[i] !== nums[i + 1]) || i === nums.length - 1 && nums[i - 1] !== nums[i]) return nums[i]
if (nums[i] !== nums[i - 1] && nums[i] !== nums[i + 1]) return nums[i]
}
};
第三种方法
第三种方法,利用异或运算符(^)。
异或运算符, 会先把数转成二进制再比较, 0和1异或,值为1,1和1,或者0和0异或,值为0。
所以两个相同的数异或,最后返回结果是0。
因为我们题目的数组其它数都是出现2次,只有一个出现一次。所以我们遍历数组异或,出现2次的数异或都变成0,最后就等同于出现一个的数字和0异或,返回还是数字本身。
代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
let temp = 0;
for (let i = 0; i < nums.length; i++)
temp ^= nums[i];
return temp;
}