问题形容

在整数数组中,如果一个整数的呈现频次和它的数值大小相等,咱们就称这个整数为「侥幸数」。

给你一个整数数组 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/...

思路剖析

题目简略,就是统计数组中每一项呈现的次数(统计谁呈现了几次),看看谁正好等于呈现的次数;当然可能正好有多个 谁 等于 其对应呈现的次数,这个时候,就看谁更大即可

  1. 一想到要统计数组中每一项呈现的次数,咱们就会想到应用Map汇合进行统计

    1. 比方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)    }}
      1. 而后再应用forof遍历map汇合,做次数判断即可
  2. 或者想到应用对象Object统计

    1. 比方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);
    2. 或者应用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);
    3. 而后再应用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的应用...

集体愚见:前端同学刷力扣算法题,倡议只刷简略和中等类型就行了。至于艰难题目,应该不必去钻研,毕竟咱们也不是应聘算法工程师这一个岗位。

而刷算法的目标,一方面是去晋升开发中数据加工组装的能力(如:后端返回的数据结构很奇葩,且不违心批改;只能前端本人加工成能用的构造啦)

另一方面就是可能在某个中央,应用某种算法操作,可能晋升性能放慢效率

再一个就是为了应酬面试啦