求教:Top K高频元素算法sort方法中b[1]-a[1]的逻辑
LeetCode《Top K高频元素》JavaScript解法sort逻辑解析
针对你遇到的问题,拆解一下sort方法的核心逻辑:
1. 先搞懂Array.sort()的比较函数规则
JavaScript里的Array.sort()会遍历数组,两两取出元素传入比较函数,参数a和b就是当前正在对比的两个元素,不是固定对应数组的某个索引。比较函数的返回值决定了元素的排序:
- 返回正数:交换
a和b的位置,把b放到a前面 - 返回负数:不交换,保持
a在b前面 - 返回0:位置不变
2. 为什么用b[1] - a[1]?
你的测试用例里,Object.entries(storage)得到的是[[1,4],[3,3],[2,1]],每个子数组的[1]位置是元素的出现频率。我们需要按频率从高到低降序排列,所以:
- 当
b的频率(b[1])大于a的频率(a[1])时,b[1]-a[1]是正数,交换位置,让频率高的b排在前面 - 比如对比
[3,3](a)和[1,4](b),4-3=1>0,交换后[1,4]就跑到[3,3]前面了 - 如果写成
a[1]-b[1],就会变成频率升序排列,不符合取前k个高频元素的需求
3. 为什么打印的a[1]和b[1]不是对应同一个索引?
这是sort内部的比较流程导致的:
sort会多次调用比较函数,每次对比的元素对都不一样:
- 第一次可能对比数组里的第2个元素
[3,3](a)和第1个元素[1,4](b),所以你打印b[1]得到4,a[1]得到3 - 第二次可能对比数组里的第3个元素
[2,1](a)和第2个元素[3,3](b),所以打印b[1]得到3,a[1]得到1 - 这些两两对比都是sort内部为了让数组有序而进行的操作,不是固定从某个索引开始一一对应
完整代码回顾
var topKFrequent = (nums, k) => { let storage = {} for(let num of nums){ storage[num] = (storage[num] ?? 0) + 1 } return Object.entries(storage).sort((a,b) => b[1] - a[1]).map(val=>Number(val[0])).slice(0,k); }
用你的测试用例nums=[1,1,1,1,3,3,3,2,2],排序后得到[[1,4],[3,3],[2,1]],再通过map提取元素值,slice(0,2)取前2个,最终结果就是[1,3],符合题目要求。
内容的提问来源于stack exchange,提问作者poopmachine
相关产品推荐
相关产品推荐

