问题描述~只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
力扣原题目地址:https://leetcode.cn/problems/...
解决方案
方案一 使用map统计各个项出现的次数,看谁出现的次数是一
var singleNumber = function (nums) {
let map = new Map() // 1. 创建一个map用来统计数据
for (let i = 0; i < nums.length; i++) { // 2. 遍历数组开始统计
// 3. 一开始map集合是空的,所以继续往下看
if (map.has(nums[i])) { // 5. 后续来了一项,新来的这一项原集合中有一样的项
let conut = map.get(nums[i]) // 6. 就看看原集合中这一项出现了几次
conut = conut + 1 // 7. 把原有次数新增一次
map.set(nums[i], conut) // 8. 然后更新次数
} else { // 4. 来一项,就把这一项存进map里面,key是这一项,value是这一项出现的次数
map.set(nums[i], 1)
}
}
// 9. 经过这么一波操作,map集合中就记录了,各个项出现的次数了
for (const [key, value] of map) { // 10. 使用forof遍历集合
if (value === 1) { // 11. 看看谁出现的次数是一次
return key // 12. 就把对应项返回出去告知即可
}
}
};
当然这里也可以使用对象去统计次数,一个道理,在此不赘述
方案二 若某一项只出现了一次则indexof和lastIndexOf值相等
- 若某个数只出现了一次,则indexof和lastIndexOf的值必定相等
- 若某个数出现了两次,则indexof和lastIndexOf的值必定不相等
var singleNumber = function (nums) {
for (let i = 0; i < nums.length; i++) {
let item = nums[i]
if (nums.indexOf(item) === nums.lastIndexOf(item)) {
return item
}
}
};
注意:indexof和lastIndexOf的区别:
- indexof查询的某个元素首次出现的索引(从左往右查)
- lastIndexOf某个元素最后一次出现的位置(区别就是从右往左查)
- 二者返回的索引,都是从左往右走的索引
方案三 使用异或运算(官方推荐)
这个异或运算的确没怎么想到,异或规则,简要如下:
- 任何数值异或0等于数值它本身
- 两个数值的异或,相同为0,相异为1
故代码如下:
var singleNumber = function (nums) {
let val = 0; // 1. 定义初始值为0
nums.forEach((item) => {
val = val ^ item // 2. 循环异或
})
return val // 3. 最终的值就是结果
};
问题描述~多数元素
这个多数元素的题目也可以使用统计次数的思路去实现
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3]
输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2
力扣原题目地址:https://leetcode.cn/problems/...
解决方案
方案一,使用map统计次数,并对比是否大于数组长度的一半
var majorityElement = function (nums) {
let map = new Map()
for (let i = 0; i < nums.length; i++) {
if (map.has(nums[i])) {
let conut = map.get(nums[i])
conut = conut + 1
map.set(nums[i], conut)
} else {
map.set(nums[i], 1)
}
}
for (const [key, value] of map) {
if (value > nums.length / 2) {
return key
}
}
};
方案二,中位数判定
找规律:
如果有一个数字出现的频率大于n/2,也就是说,这个数字出现了很多次,比如有五个雪糕,有三个都是小布丁。
那么就是找到雪糕的中间数,即可找到这个出现次数超过n/2的数。所以先排序,然后再取中间数即可
var majorityElement = function (nums) {
nums.sort(function (a, b) { // 1. 排个序
return a - b
})
let middle = Math.floor(nums.length / 2) // 2. 取到中间数
return nums[middle] // 3. 返回就是
}
总结
题目不难,方法有很多种,不过咱们还是要预留一种保底的方法,就是使用map集合进行统计的方式。
毕竟面试中,可能比较紧张,其他的一些方式可能想不起来了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。