携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情
前言
今天的题目为困难,题目虽然是困难难度,但是总的来说考察的就是一个分析处理,能够总结出题目要求的一些条件,也是能够通过比较简单的判断逻辑来完成题目的。
每日一题
今天的题目是 1224. 最大相等频率,难度为困难
-
给你一个正整数数组 nums,请你帮忙从该数组中找出能满足下面要求的 最长 前缀,并返回该前缀的长度:
-
从前缀中 恰好删除一个 元素后,剩下每个数字的出现次数都相同。
-
如果删除这个元素后没有剩余元素存在,仍可认为每个数字都具有相同的出现次数(也就是 0 次)。
示例 1:
输入:nums = [2,2,1,1,5,3,3,5]
输出:7
解释:对于长度为 7 的子数组 [2,2,1,1,5,3,3],如果我们从中删去 nums[4] = 5,就可以得到 [2,2,1,1,3,3],里面每个数字都出现了两次。
示例 2:
输入:nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]
输出:13
提示:
- 2 <= nums.length <= 105
- 1 <= nums[i] <= 105
题解
遍历前缀
通过一次循环,我们就能够拿到所有的前缀,那么就只要去判断什么样的子串会满足题目的要求,根据题目的意思,满足题目要求的情况有三种。
- 每一个数字都只出现了一次,比如说 1,2,3,4,5 那么去掉其中任意一个数字都可以满足条件
- 存在一个数字唯一,其余数字都是大于1的个数,并且个数相等,比如说 111,222,3 那么删除掉3就可以满足题目的要求
- 存在一个数字的个数,比其他数字多一个,其他数字都比它少一个,这样删除掉一个这个数字,也能够满足题目要求,比如说 11,22,333 删除掉一个3就能够满足题意。
那么根据这三种情况,我们最少需要一个哈希表去纪录下每一个数字出现的次数,在根据第三种情况来看,我们还需要一个max参数来纪录下出现最多数字的次数,以及出现次数为这个次数的数字的个数 maxCount。
-
第一种情况下的要求是max为1,也就是数字最多都只有一个
-
第二种情况下要求为 max * maxCount 为 n-1 也就是数字出现最多的次数,乘以出现次数为这个次数的数字个数,应该刚好是长度减去一个,那一个也就是特殊的那个
-
第三种情况,需要满足 maxCount = 1 ,并且其他数字出现次数都是max-1.
那么综合上面的条件,我们就可以利用哈希表来进行存储判断。
function maxEqualFreq(nums: number[]): number {
let map = new Map<number,number>();
let max: number = 0
let countMax: number = 0
let ans:number = 0;
for (let i = 0; i < nums.length; i++) {
let num = nums[i];
if (!map.has(num)) map.set(num, 0);
let count = map.get(num);
if (max === count) {
max++;
countMax = 1;
} else if (count + 1 === max) {
countMax++;
}
map.set(num, count+1);
if (max === 1 || countMax*max === i ||
(countMax === 1 && max === i/map.size + 1)) {
ans = i+1;
}
}
return ans;
};