元素频率
一、统计元素频率
1.1 通过对象
const array = [1,1,3,3,3,3,3,6,7,7,7,7,7,8,8,8,8];
const result = array.reduce(function(accumulator,currentValue,index,arr){
if(currentValue in accumulator){
accumulator[currentValue]++
}else{
accumulator[currentValue] = 1;
}
return accumulator;
},{});
console.log(result);
1.2 通过Map
function countFrequency(nums){
return nums.reduce((prev,curr)=>prev.set(curr,(prev.get(curr)||0)+1),new Map())
}
二、多数元素
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1:
输入:[3,2,3]
输出:3
示例2:
输入:[2,2,1,1,1,2,2]
输出:2
2.1 Boyer-Moore 投票算法
思路: Boyer-Moore
摩尔投票思想, 算法利用票数抵消的思想, 票数为 0
时更新候选人, 每次遇到与候选人相同的数字,就增加票数, 不同的数字则减少票数。最终, 多数元素(出现次数超过 n/2
次)一定会留下正票,因此能在最后胜出。
一、初始化变量:
-
count
: 用于记录当前候选元素的票数,初始为0
。 -
candidate
: 用于存储当前的候选多数元素,初始为null
。
二、遍历数组: 使用 for...of
循环遍历数组中的每个数字:
-
票数归零时更新候选人, 当票数为
0
时, 说明之前的候选人已经抵消完毕,此时将当前数字设为新的候选人。 -
票数加减, 如果当前数字等于候选人,则票数加
1
, 否则票数减1
。
三、返回结果: 遍历结束后,由于多数元素的出现次数超过一半,它最终会成为候选人,因此返回 candidate
即可。
function multiElement(nums) {
let count = 0;
let element = 0;
nums.forEach((value) => {
if (count === 0) {
element = value;
}
count += element === value ? 1 : -1;
});
return element;
}
-
时间复杂度:
O(n)
,只需要一次遍历。 -
空间复杂度:
O(1)
,只使用了常数级别的额外空间。
三、最高频元素的频数
元素的频数是该元素在一个数组中出现的次数。给你一个整数数组 nums
和一个整数 k
。在一步操作中,你可以选择 nums
的一个下标,并将该下标对应元素的值增加 1
。执行最多 k
次操作后,返回数组中最高频元素的最大可能频数。
示例1:
输入:nums = [1,2,4], k = 5
输出:3
解释:对第一个元素执行 3 次递增操作,对第二个元素执 2 次递增操作,此时 nums = [4,4,4] 。
4 是数组中最高频元素,频数是 3 。
示例2:
输入:nums = [1,4,8,13], k = 5
输出:2
解释:存在多种最优解决方案:
- 对第一个元素执行 3 次递增操作,此时 nums = [4,4,8,13] 。4 是数组中最高频元素,频数是 2 。
- 对第二个元素执行 4 次递增操作,此时 nums = [1,8,8,13] 。8 是数组中最高频元素,频数是 2 。
- 对第三个元素执行 5 次递增操作,此时 nums = [1,4,13,13] 。13 是数组中最高频元素,频数是 2 。