元素频率
题一、统计元素频率
方案A、通过对象
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);
方案B、通过Map
function countFrequency(nums){
return nums.reduce((prev,curr)=>prev.set(curr,(prev.get(curr)||0)+1),new Map())
}
题二、多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1:
输入:[3,2,3]
输出:3
示例2:
输入:[2,2,1,1,1,2,2]
输出:2
方案A、排序法
思路: 由于数组中总是存在多数元素,如果将数组 nums 中的所有元素按照单调递增或单调递减的顺序排序,那么下标为 n/2 的元素(下标从 0 开始)一定是众数。
- 通过快速排序算法对数组排序
- 返回排序后的 nums[Math.floor(nums.length/2)]
function quickSort(nums,start,end){
if(start>=end){
return;
}
let left=start;
let right=end;
let pivot=nums[Math.floor((left+right)/2)];
while(left<=right){
while(nums[left]<pivot){
left++;
}
while(nums[right]>pivot){
right--;
}
if(left<=right){
[nums[left],nums[right]]=[nums[right],nums[left]];
left++;
right--;
}
}
quickSort(nums,start,right);
quickSort(nums,left,end);
}
function majorityElement(nums) {
quickSort(nums,0,nums.length-1);
return nums[Math.floor(nums.length/2)]
};
性能分析:
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
方案B、Map 法
思路:遍历整个数组,对记录每个数值出现的次数(利用HashMap,其中key为数值,value为出现次数); 接着遍历HashMap中的每个Entry,寻找value值> nums.length / 2的key即可。
function majorityElement(nums) {
const map=nums.reduce((prev,curr)=>prev.set(curr,(prev.get(curr)||0)+1),new Map())
for(let item of map){
if(item[1]>Math.floor(nums.length/2)){
return item[0]
}
}
};
性能分析:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
摩尔投票算法
思路:如果我们把众数记为 +1,把其他数记为 -1,将它们全部加起来,显然和大于 0,从结果本身我们可以看出众数比其他数多。
Boyer-Moore 算法的详细步骤:
- 我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
- 我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:
- 如果 x 与 candidate 相等,那么计数器 count 的值增加 1;
- 如果 x 与 candidate 不等,那么计数器 count 的值减少 1。
- 在遍历完成后,candidate 即为整个数组的众数。
function majorityElement(nums) {
let count=0;
let candidate;
for(let item of nums){
if(count==0){
candidate=item;
}
count += (item == candidate) ? 1 : -1;
}
return candidate;
}
性能分析:
- 时间复杂度: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 。