力扣每日一题(1224:最大相等频率)

118 阅读3分钟

题目

给你一个正整数数组 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

练习刷了三天力扣题,题目一天比一天好读懂,难度一天比一天大,简单易懂的三行题目折磨了我大半天终于把题目做出来了,就这还是看了一眼题解才做出来的😭。

快乐做题,先从把TS的红线去了再说吧😁。 image.png

image.png 现在看着顺眼多了。

言归正传,这道题目没有什么套路可言,就是硬算,遍历一次nums数组,每次都看一下现在是否符合题目的要求,即删除一个数后,每种数字的数量一样多。

要满足这个条件,需要满足下列三个条件中的一个即可

  • 每个数字都只出现了一次
  • 一个数字出现了n+1次,其他数字出现了n次
  • 一个数字出现了1次,其他数字出现了n次

只要可以满足上述三个条件中的一个,就可以达到题目所需要的效果。

这个思路并不难想到,难点在于怎么样去记录每个数字出现的次数以及判断是否满足上述三个条件中的一个。

这里用到的是TypeScript,为了方便记录,需要维护两个Map对象,一个Map用来记录每个数字出现的次数:count,另一个Map用来记录数字出现次数的次数frep(),比如出现2次的数字有2个。

不可能每次都要遍历一边Map数组,这样时间复杂度就提高了,所以我们还需要记录一个数据:数字出现的最大次数是多少,代码里我们给他记为maxCount

maxCount还有一个用处,如果要遍历map太耗费时间了,maxCount存在的数量记为frep(maxCount),这两个数相乘就可以得到数量。我们现在来看三个分别改如何满足。

  • 如果maxCount为1,那么代表满足第一个条件。
  • 要满足第二个条件,n应该为maxCount - 1frep(maxCount - 1) * (maxCount - 1) 得到的数据加上frep(maxCount) * maxCount 得到的数据为i(循环遍历的i),即frep(maxCount - 1) * (maxCount - 1) + frep(maxCount) * maxCount === i,且frep(maxCount) 为1
  • 要满足第三个条件,n就是maxCount,那么需要frep(maxCount) * maxCount + frep(1) === i,并且frep(1) 为1

不知道这里解释清楚了没,如果没看懂的话可以评论说下,我再解释解释😁

附上TS代码

function maxEqualFreq(nums: number[]): number {
    let countMap = new Map()
    let frepMap = new Map()
    let maxCount: number = 0
    let res: number = 0
    for (let i = 0; i < nums.length; i++) {
        const num: number = nums[i]
        if (!countMap.has(num)) {
            countMap.set(num, 1)
        } else {
            countMap.set(num, countMap.get(num) + 1)
        }
        if (!frepMap.has(countMap.get(num))) {
            frepMap.set(countMap.get(num), 1)
        } else {
            frepMap.set(countMap.get(num), frepMap.get(countMap.get(num)) + 1)
        }
        maxCount = Math.max(maxCount, countMap.get(num))
        if (frepMap.has(countMap.get(num) - 1)) {
            frepMap.set(countMap.get(num) - 1, frepMap.get(countMap.get(num) - 1) - 1)
        }
        if (
            maxCount === 1  || //条件1
            frepMap.get(maxCount) === 1 && frepMap.get(maxCount) * maxCount + frepMap.get(maxCount - 1) * (maxCount - 1) === i + 1 || // 条件2
            frepMap.get(maxCount) * maxCount + frepMap.get(1) === i + 1 && frepMap.get(1) === 1 //条件3
        ) {
           res = i + 1
        }
    }
    return res
};

最重要的就是最后一个if里面的三个判断条件,上面那些就是在维护countMapmaxCountfrepMap

总结

  • 这道题在难点在判断条件和countMap、frepMap的维护更新,可以多打断点或者console.log()看看这两个数据是不是出了问题,如果没问题还是没通过,可以看看判断条件哪里不对。
  • 遇到困难的题目先不要慌,这不是考试,真的做不来可以看看题解,看完题解之后自己做一遍对自己提升也是有帮助的。

最近工作太忙,前几天做完题目后都没时间整理,隔了好几天才把文章写好,这几天力扣网也没刷,可怜的打工仔啊😭。

往后如果项目不着急的话会力扣每日一题会做一遍然后整理好思路把文章发出来。希望最近不要太忙了😭