Medium
题目描述
给你一个整数数组 nums 和一个整数 digit。
返回 digit 在 nums 中所有元素的十进制表示中出现的总次数。
示例 1:
输入:nums = [12,54,32,22], digit = 2
输出:4
解释:
数字 2 在 12 和 32 中各出现一次,在 22 中出现两次。因此,数字 2 的总出现次数是 4。
示例 2:
输入:nums = [1,34,7], digit = 9
输出:0
解释:
数字 9 在 nums 中任何元素的十进制表示中都没有出现,所以数字 9 的总出现次数是 0。
提示:
1 <= nums.length <= 10001 <= nums[i] <= 10^60 <= digit <= 9
解题思路
这道题要求统计指定数字在数组所有元素中的出现次数,需要检查每个数字的每一位。
核心思路: 遍历数组中的每个数字,对于每个数字,逐位提取其十进制位数并与目标数字进行比较。
主要解法:
字符串转换法:将每个数字转为字符串,遍历每个字符统计目标数字出现次数。这种方法简单直观,代码易读。
数学取模法:通过不断除以10和取模运算来提取数字的每一位。这种方法避免了字符串转换的开销。
数学递归法:递归地处理每个数字的位数提取。
从效率角度考虑,数学取模法在大数据量下表现更好,因为避免了字符串操作的开销。不过在本题的约束条件下(数组长度最多1000,数字最大10^6),两种方法性能差异不大。
推荐解法:数学取模法,因为它直接在数值上操作,避免了类型转换,代码也相对简洁。
代码实现
class Solution {
public:
int countDigitOccurrences(vector<int>& nums, int digit) {
int count = 0;
for (int num : nums) {
if (num == 0) {
if (digit == 0) count++;
continue;
}
while (num > 0) {
if (num % 10 == digit) {
count++;
}
num /= 10;
}
}
return count;
}
};
class Solution:
def countDigitOccurrences(self, nums: list[int], digit: int) -> int:
count = 0
for num in nums:
if num == 0:
if digit == 0:
count += 1
continue
while num > 0:
if num % 10 == digit:
count += 1
num //= 10
return count
public class Solution {
public int CountDigitOccurrences(int[] nums, int digit) {
int count = 0;
foreach (int num in nums) {
int temp = num;
if (temp == 0) {
if (digit == 0) count++;
continue;
}
while (temp > 0) {
if (temp % 10 == digit) {
count++;
}
temp /= 10;
}
}
return count;
}
}
var countDigitOccurrences = function(nums, digit) {
let count = 0;
for (let num of nums) {
let str = num.toString();
for (let char of str) {
if (parseInt(char) === digit) {
count++;
}
}
}
return count;
};
复杂度分析
| 项目 | 复杂度 |
|---|---|
| 时间复杂度 | O(n × log m) |
| 空间复杂度 | O(1) |
其中 n 是数组长度,m 是数组中数字的最大值。每个数字需要 O(log m) 时间来提取所有位数。