跳至主要內容

1399. 统计最大组的数目


1399. 统计最大组的数目

🟢   🔖  哈希表 数学  🔗 力扣open in new window LeetCodeopen in new window

题目

You are given an integer n.

Each number from 1 to n is grouped according to the sum of its digits.

Return the number of groups that have the largest size.

Example 1:

Input: n = 13

Output: 4

Explanation: There are 9 groups in total, they are grouped according sum of its digits of numbers from 1 to 13:

[1,10], [2,11], [3,12], [4,13], [5], [6], [7], [8], [9].

There are 4 groups with largest size.

Example 2:

Input: n = 2

Output: 2

Explanation: There are 2 groups [1], [2] of size 1.

Constraints:

  • 1 <= n <= 10^4

题目大意

给你一个整数 n 。请你先求出从 1n 的每个整数 10 进制表示下的数位和(每一位上的数字相加),然后把数位和相等的数字放到同一个组中。

请你统计每个组中的数字数目,并返回数字数目并列最多的组有多少个。

示例 1:

输入: n = 13

输出: 4

解释: 总共有 9 个组,将 1 到 13 按数位求和后这些组分别是:

[1,10],[2,11],[3,12],[4,13],[5],[6],[7],[8],[9]。总共有 4 个组拥有的数字并列最多。

示例 2:

输入: n = 2

输出: 2

解释: 总共有 2 个大小为 1 的组 [1],[2]。

示例 3:

输入: n = 15

输出: 6

示例 4:

输入: n = 24

输出: 5

提示:

  • 1 <= n <= 10^4

解题思路

  1. 理解数字和的计算
    对于一个整数 i,其数字和可以通过计算所有位的和得到。例如,123 的数字和是 1 + 2 + 3 = 6
    我们可以通过动态规划(dp 表示数字和的缓存)快速计算 i 的数字和:

    • dp[i] = dp[Math.floor(i / 10)] + i % 10
    • 即数字和等于去掉最后一位的数字和,加上最后一位。
    • 可以看出需要缓存 dp 的最大值为 Math.max(n / 10, 10)
  2. 统计数字和的频率
    用一个数组 count 来记录每个数字和的出现频率,其中索引表示数字和(从 1 开始)。
    遍历从 1n 的所有数字,计算每个数字的数字和,并更新对应的频率。

  3. 计算最大组的数量

    • 找到频率数组中最大的值 largest
    • 统计频率等于 largest 的组数。
  4. 返回最大组的数量。

复杂度分析

  • 时间复杂度O(n)
    • 遍历数字:从 1n 需要遍历一次,时间复杂度为 O(n)
    • 计算最大值和过滤:对 count 数组操作是常数级别的,时间复杂度为 O(1)(最多 4 * 9 = 36 项)。
  • 空间复杂度O(1),动态规划缓存 dp 和频率数组 count 的空间均为有限大小的常数级。

代码

/**
 * @param {number} n
 * @return {number}
 */
var countLargestGroup = function (n) {
	let dp = { 0: 0 }; // 缓存数字和的动态规划表
	const dpSize = Math.max(n / 10, 10); // 缓存大小的最大值
	let count = new Array(4 * 9).fill(0); // 统计每个数字和的频率

	for (let i = 1; i <= n; i++) {
		const quotient = Math.floor(i / 10); // 十位
		const reminder = i % 10; // 个位
		const digitSum = reminder + dp[quotient]; // 当前数字的数字和

		if (i <= dpSize) {
			dp[i] = digitSum; // 更新动态规划缓存
		}
		count[digitSum - 1]++; // 更新数字和的频率
	}

	const largest = Math.max(...count); // 找到最大组大小
	return count.filter((i) => i == largest).length; // 统计最大组的数量
};