【每日一题记录】1224. 最大相等频率

126 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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;
}

image.png

其他思路分享

宫水三叶大神的思路十分巧妙 值得记录一下: 我们使用 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」)。

我是短袖撸码蒂尔尼
一名热爱阿森纳的前端工程师
如果本文对您有帮助,可以给一个免费的赞吗?谢谢!

名片.jpg