问题描述
在整数数组中,如果一个整数的出现频次和它的数值大小相等,我们就称这个整数为「幸运数」。
给你一个整数数组 arr,请你从中找出并返回一个幸运数。
如果数组中存在多个幸运数,只需返回 最大 的那个。 如果数组中不含幸运数,则返回 -1 。
示例 1:
输入:arr = [2,2,3,4]
输出:2
解释:数组中唯一的幸运数是 2 ,因为数值 2 的出现频次也是 2 。
示例 2:
输入:arr = [1,2,2,3,3,3]
输出:3
解释:1、2 以及 3 都是幸运数,只需要返回其中最大的 3 。
示例 3:
输入:arr = [2,2,2,3,3]
输出:-1
解释:数组中不存在幸运数。
示例 4:
输入:arr = [5]
输出:-1
示例 5:
输入:arr = [7,7,7,7,7,7,7]
输出:7
力扣原题目地址:https://leetcode.cn/problems/...
思路分析
题目简单,就是统计数组中每一项出现的次数(统计谁出现了几次),看看谁正好等于出现的次数;当然可能正好有多个 谁 等于 其对应出现的次数,这个时候,就看谁更大即可
一想到要统计数组中每一项出现的次数,我们就会想到使用Map集合进行统计
比如for循环数组,然后往map里追加,map中存储的键值对中的key为数组中的项,value为数组中这一项出现的次数。代码:
let map = new Map() for (let i = 0; i < arr.length; i++) { if (map.has(arr[i])) { let count = map.get(arr[i]) count = count + 1 map.set(arr[i], count) } else { map.set(arr[i], 1) } }
- 然后再使用
forof
遍历map集合,做次数判断即可
- 然后再使用
或者想到使用对象Object统计
比如for循环数组,然后往对象中去添加。对象中的key为数组中的项,value为数组中这一项出现的次数。代码
let obj = {} for (let i = 0; i < arr.length; i++) { let item = arr[i] if (item in obj) { let count = obj[item] count = count + 1 obj[item] = count } else { obj[item] = 1 } } console.log(obj);
或者使用reduce循环去统计操作次数
let res = arr.reduce((tempObj, item) => { if (item in tempObj) { let count = tempObj[item] count = count + 1 tempObj[item] = count } else { tempObj[item] = 1 } return tempObj }, {}) console.log(res);
- 然后再使用
forin
遍历对象,做次数判断即可
代码
使用Map
var findLucky = function (arr) {
// 1. 统计次数
let map = new Map()
for (let i = 0; i < arr.length; i++) {
if (map.has(arr[i])) {
let count = map.get(arr[i])
count = count + 1
map.set(arr[i], count)
} else {
map.set(arr[i], 1)
}
}
// 2. 定义初始luckyNum,比如没有(没有返回-1)
let luckyNum = -1
// 3. 遍历map集合
for (const [key, value] of map) {
if (key === value) { // 若某一项也等于其对应出现次数
key > luckyNum ? luckyNum = key : '' // 就做一个大小的判断(因为要取最大的那个)
}
}
return luckyNum // 最后返回之即可
};
使用Object
var findLucky = function (arr) {
// 1. 使用对象的方式 reduce函数
let res = arr.reduce((tempObj, item) => {
if (item in tempObj) {
let count = tempObj[item]
count = count + 1
tempObj[item] = count
} else {
tempObj[item] = 1
}
return tempObj
}, {})
let luckyNum = -1
for (const key in res) {
/* 注意这里不能直接判断key === res[key],因为对象中的key直接循环默认为字符串
但是value(res[key])是数字类型的。所以要把数字类型也转换为字符串类型的 */
/* 或者使用双等于号,不使用三等于号。毕竟js会做类型转换。字符串'1'是弱等于数字1的
if (key == res[key]) { ...... } */
if (key === res[key] + '') {
res[key] > luckyNum ? luckyNum = res[key] : ''
}
}
return luckyNum
};
总结
如果leetcode题目刷多了,会发现,一些题目是另外一些简单题目的变形。
比如这一题考查的还是数组中统计项出现的次数(使用Map集合统计、使用Object统计)
以及Map的循环forof的使用,或者reduce函数的使用、forin的使用...
个人愚见:前端同学刷力扣算法题,建议只刷简单和中等类型就行了。至于困难题目,应该不用去研究,毕竟咱们也不是应聘算法工程师这一个岗位。
而刷算法的目的,一方面是去提升开发中数据加工组装的能力(如:后端返回的数据结构很奇葩,且不愿意修改;只能前端自己加工成能用的结构啦)
另一方面就是可能在某个地方,使用某种算法操作,能够提升性能加快效率
再一个就是为了应付面试啦
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。