LeetCode 记录-1636. 按照频率将数组升序排序

130 阅读1分钟

LeetCode 记录-1636. 按照频率将数组升序排序

我的解法

思路

image.png

首先,看到题目中要按频率升序排列,考虑到统计频率,就想到用 map 来统计。然后再用 value 进行排序。然后,对于频率相同的元素,再用数值 key 进行降序排列。


代码

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var frequencySort = function (nums) {
  const cntMap = new Map();
  for (let num of nums) {
    cntMap.set(num, (cntMap.get(num) || 0) + 1);
  }

  const res = [];
  [...cntMap.entries()]
    .sort((a, b) => {
      if (a[1] === b[1]) {
        return b[0] - a[0];
      }
      return a[1] - b[1];
    })
    .forEach((pair) => {
      res.push(...new Array(pair[1]).fill(pair[0]));
    });

  return res;
};

复杂度分析(自我分析,不一定对)

时间复杂度

O(nlogn)O(nlogn),因为涉及到排序,考虑到最差的情况,所有的数值各不相同,频率均为 1,那么时间复杂度就为O(nlogn)O(nlogn)

空间复杂度

O(n)O(n), 在最差的情况下,map 所需要的空间和 n 成正比,所以为O(n)O(n)


官方解法 :模拟

思路

按着题目的要求,先算出数组 \textit{nums}nums 中各元素的频率,然后按照元素频率和数值对数组进行排序即可。

代码

var frequencySort = function (nums) {
  const cnt = new Map();
  for (const num of nums) {
    cnt.set(num, (cnt.get(num) || 0) + 1);
  }
  const list = [...nums];
  list.sort((a, b) => {
    const cnt1 = cnt.get(a),
      cnt2 = cnt.get(b);
    return cnt1 !== cnt2 ? cnt1 - cnt2 : b - a;
  });
  const length = nums.length;
  for (let i = 0; i < length; i++) {
    nums[i] = list[i];
  }
  return nums;
};

复杂度分析

时间复杂度

O(nlogn)O(nlogn),其中 n 是数组 nums 的长度,排序消耗O(nlogn)O(nlogn)时间

空间复杂度

O(n)O(n), 储蓄数组元素的频率的哈希表消耗 O(n)O(n)空间