携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情
题目描述
给定一个数组arr,要求找出数组的最大前缀,且该最大前缀满足:删除该前缀的某一元素后,前缀中的其他元素的个数相同。返回arr满足要求的最大前缀的长度。
例1:输入:arr=[10,2,8,9,3,8,1,5,2,3,7,6] 输出:8
解释:该用例中当前缀长度为8时,去除元素8后,剩余的元素个数均为1,不存在满足题目要求的更长的前缀,所以最大前缀的长度为8。
例1:输入:arr=[1,1] 输出:2
解释:当取前缀的长度为2时,去除一个元素1,剩下的元素1的个数为1,符合题目要求所以最长前缀长度为2。
本题值得注意的地方:
- 当去除一个元素后剩下的前缀元素的个数为0时也是符合题意的。
原题地址:1224. 最大相等频率
解题思路
通过题中对前缀的要求可以总结出以下几种情况:
- 当前缀中所有的元素出现的次数都为1次时,在删除任意一个元素后其他元素出现的次数都是相同的为1。符合题目要求。
- 当前缀中有一个元素出现的次数为1,其他元素出现的次数是相同的,这种情况在删除出现次数为1的那个元素后其他元素出现的次数是相同的,符合题目要求,例如[0,0,1,2,2],在删除元素1后剩下的元素个数相同。
- 当前缀中元素的出现次数有两种情况,且较大的次数与较小的次数差值为1并且出现次数为较大次数的元素的个数为1次。这时删除较大次数的一个元素,剩下的元素出现的次数是相同的,例如[0,0,0,1,1],在删除0后剩下的元素出现的次数相同。
实现代码
class Solution {
public:
int maxEqualFreq(vector<int>& nums) {
int res=1, maxfreq=1;
// 记录当前字串中元素出现的次数、每个次数的元素数
map<int,int> count,freq;
// 依次处理前缀
for(int i=0; i<nums.size(); i++){
// 当前元素出现的次数加1
count[nums[i]]++;
// 如果当前元素出现的次数大于1,则将当前次数-1中统计的元素数-1,将当前次数统计的元素数+1
if(count[nums[i]]>1) freq[count[nums[i]]-1]--;
freq[count[nums[i]]]++;
// 维护元素出现的最大次数
maxfreq=max(maxfreq,count[nums[i]]);
// 对应上面结论的三种情况
if(maxfreq == 1 || freq[maxfreq]*maxfreq + freq[maxfreq-1]*(maxfreq-1) == i+1&&freq[maxfreq] == 1 || freq[maxfreq]*maxfreq+1==i+1 && freq[1] == 1) res=i+1;
}
return res;
}
};