问题描述

给你一个整数数组 nums ,请你将数组按照每个值的频率 升序 排序。如果有多个值的频率相同,请你按照数值本身将它们 降序 排序。 

请你返回排序后的数组。

示例 1:

输入:nums = [1,1,2,2,2,3]
输出:[3,1,1,2,2,2]
解释:'3' 频率为 1,'1' 频率为 2,'2' 频率为 3 。

示例 2:

输入:nums = [2,3,1,3,2]
输出:[1,3,3,2,2]
解释:'2' 和 '3' 频率都为 2 ,所以它们之间按照数值本身降序排序。

示例 3:

输入:nums = [-1,1,-6,4,5,-6,1,4,1]
输出:[5,-1,4,4,-6,-6,1,1,1]
力扣原题目地址:https://leetcode.cn/problems/...
 

知识点回顾之Map集合和二维数组

我们知道Map集合可以用于存储一组组键值对数据。比如我们要创建一个Map集合,集合中有三组数据,分别对应为姓名和年龄。

原始数据如下:

姓名    年龄
孙悟空  500
猪八戒  88
沙和尚  1000

创建出来的Map集合如下图

接下来回顾一下创建这个Map集合的两种方式

使用Map.set()方法创建Map集合

一般情况下,我们都是使用Map的set方法去创建自己想要的集合,如下代码:

let map1 = new Map()
map1.set('孙悟空', 500)
map1.set('猪八戒', 88)
map1.set('沙和尚', 1000)
console.log('map1', map1);

使用二维数组创建Map集合

既然Map集合可以存储一组组键值对的数据,那么我们可以把这个一组组数据,当成一个个只包含两个项(第0项是键key、第二项是值value)的数组,然后把整个集合当成一个大数组。

于是一个二维数组就应运而生了。所以在构造函数的协同下,我们可以在实例化Map对象的时候,传入一个二维数组,便是可以达到同样的效果,如下代码:

let map2 = new Map(
    [
        ['孙悟空', 500],
        ['猪八戒', 88],
        ['沙和尚', 1000],
    ]
)
console.log('map2', map2);

由上述两个案例,可以知道Map集合,好像就是二维数组的一种变形方式,一种特殊的二维数组,当然实际不是哦。

  • 上方案例使用二维数组创建Map集合可理解为,把二维数组转成对应Map集合;
  • 同样的,Map集合也可转为二维数组,使用Array.from(map)即可
注意,上述二维数组转Map集合案例,是固定项个数。如 内层数组只有两项key项、value项。如果再多几项,会忽略后续的项。因为Map集合的一组数据只有key和value。如下代码
let map = new Map(
        [
            ['孙悟空', 500, '花果山水帘洞'],
            ['猪八戒', 88, '高老庄'],
            ['沙和尚', 1000, '通天河'],
        ]
  )
console.log('map', map);

打印出来的结果如下:

 {'孙悟空' => 500, '猪八戒' => 88, '沙和尚' => 1000}

就会忽略二维数组中内层数组的第3项 ‘花果山水帘洞、高老庄、通天河’,因为Map集合每一项只能存储两项,键值对

为什么要提到二维数组呢?因为题目需要

解题思路分析

  • 第一步,使用Map集合统计数组中每一项出现的次数(频率)
  • 第二步,因为要把数组做升序排序,所以需要将Map集合转化成二维数组,并调用Array.sort()方法给二维数组做排序
  • 然后再创建一个空数组,双层遍历二维数组,将对应项,追加到空数组中去,并返回即可

解题代码

就以下方定义的nums数组做用例进行理解吧

let nums = [1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 4, 3]
var frequencySort = function (nums) {
    // 第一步,使用Map集合统计各项出现的次数
    let map = new Map()
    for (let i = 0; i < nums.length; i++) {
        if (map.has(nums[i])) {
            let count = map.get(nums[i])
            count = count + 1
            map.set(nums[i], count)
        } else {
            map.set(nums[i], 1)
        }
    }
    // 第二步,将统计好频率次数的Map集合转成二维数组并相应排序
    let mmap = Array.from(map) // 注意这里要排序两次
    mmap.sort((a, b) => {
        return b[0] - a[0] // 第一次排序,按照自身从大到小
    })
    mmap.sort((a, b) => {
        return a[1] - b[1] // 第二次排序,按照出现的频率从小到大
    })
    // 第三步,定义空数组,并循环二维数组追加即可
    let result = []
    mmap.forEach((item) => {
        for (let j = 0; j < item[1]; j++) { // 注意j小于item[1],item[1]即为出现的次数
            result.push(item[0]) // item[0] 指的是原始数组中的每一项;item[0]、item[1] 即为 谁、出现了几次
        }
    })
    return result
};
console.log('结果', frequencySort(nums)); // [4, 3, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1]

总结

题目考查主要是:

  • Map集合的使用
  • 二维数组的简单应用
  • 二维数组的排序

水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负