携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
大家好 我是短袖撸码蒂尔尼。今天带来的是一道在LeetCode上的题目,题目难度为困难。就在此为大家分享一下解答思路。
题目阐述
给你一个正整数数组 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
思路阐述
这个题目刚拿到的时候我感觉就离不开哈希表了
第一时间脑海的想法是:
- 其他元素的出现次数是一样的?
- 要么删除出现次数最多的元素max 要么删除出现次数最少的元素min
然后ac的过程中,渐渐的把题目归纳为三种情况:
所有数的出现次数都是 1,去掉任意一个数都满足条件 去掉一个数后其他数的出现次数相等,如[2,2,1,1,3]去掉一个 3 去掉一个数后包含当前数的所有数出现次数相等,如[2,2,1,1,3,3,3]去掉一个 3
那这时候,我需要设计两个哈希表 去记录每个元素的出现次数map1,和出现次数为i时的元素个数map2
function maxEqualFreq(nums: number[]) {
const map1 = new Map<number, number>();
const map2 = new Map<number, number>();
let max = 0;
let maxEqualFreq = 0;
for (let i = 0; i < nums.length; i++) {
const count = map2.get(nums[i]) ?? 0;
if (count > 0) {
map1.set(count, (map1.get(count) ?? 0) - 1);
}
map2.set(nums[i], count + 1);
const curCount = map2.get(nums[i]) ?? 0;
max = Math.max(max, curCount);
map1.set(curCount, (map1.get(map2.get(nums[i]) ?? 0) ?? 0) + 1);
const maxFreqCount = map1.get(max) ?? 0;
const judge =
max === 1 ||
(maxFreqCount * max + (map1.get(max - 1) ?? 0) * (max - 1) === i + 1 &&
maxFreqCount === 1) ||
(maxFreqCount * max + 1 === i + 1 && map1.get(1) === 1);
if (judge) {
maxEqualFreq = Math.max(maxEqualFreq, i + 1);
}
}
return maxEqualFreq;
}
其他思路分享
宫水三叶大神的思路十分巧妙 值得记录一下: 我们使用 cnt 数组记录每个数的出现次数(即 cnt[i] = x 含义为数值 ii 的出现次数为 xx 次),以及使用 sum 来记录出现次数为某个值的数有多少个(即 sum[i] = x 含义为出现次数为 ii 的数值共有 xx 个),同时使用 max 来记录最大出现次数 cnt[i]cnt[i]。
从前往后处理 nums,假设当前处理到的数值为 t = nums[i]t=nums[i](前缀所含数量为 len = i + 1len=i+1)有如下几种情况,我们可以更新最大长度 ans:
max = 1max=1: 说明当前处理到的所有 nums[i]nums[i] 均只出现了一次,此时任意删除一个均满足要求;
max \times sum[max] + 1 = lenmax×sum[max]+1=len:说明有一个数值单独出现了一次(其余出现次数为 max 的数值 + 被删除的一个数 = 总数量 lenlen),删除后即满足要求;
(max - 1) \times (sum[max - 1] + 1) +1=len(max−1)×(sum[max−1]+1)+1=len:说明出现次数为 max 的数值只有一个,其余出现次数均为 max - 1,对其删除一次后即满足要求(删除该出现次数为 max 的数值后,会导致出现次数为 max - 1 的数值多一个,此时有「出现次数为 max - 1 的数值 + 被删除的一个数 = 总数量 len」)。
我是短袖撸码蒂尔尼
一名热爱阿森纳的前端工程师
如果本文对您有帮助,可以给一个免费的赞吗?谢谢!