2026-02-08:大于平均值的最小未出现正整数。用go语言,给定一个整数数组 nums。先计算数组所有元素之和除以元素个数得到平均值。然后从正整数中按从小到大的顺序查找第一个既未出现在 nums 中、又严格大于该平均值的数,并将它作为结果返回。平均值即数组元素总和除以元素个数。
1 <= nums.length <= 100。
-100 <= nums[i] <= 100。
输入: nums = [3,5]。
输出: 6。
解释:
nums 的平均值是 (3 + 5) / 2 = 8 / 2 = 4 。
大于 4 的最小未出现正整数是 6。
题目来自力扣3678。
分步骤描述
-
计算数组元素总和
代码首先初始化一个变量sum为0。然后遍历数组nums中的每一个元素,将每个元素的值累加到sum上。对于输入nums = [3, 5],总和计算为3 + 5 = 8。 -
计算平均值
平均值通过总和sum除以数组长度len(nums)得到。在Go语言中,整数除法会向下取整。对于例子[3, 5],平均值为8 / 2 = 4。 -
确定搜索起点
题目要求寻找大于平均值的最小未出现正整数。代码中max(sum/len(nums)+1, 1)这一步确保了搜索起点至少为1(因为题目要求返回的是正整数),并且是大于平均值的最小整数。对于平均值4,搜索起点为max(4+1, 1) = 5。 -
记录已出现的数字
在遍历数组累加总和的同时,代码使用了一个映射(Map)has。它将数组中的每个数字作为键(Key),对应的值(Value)设置为true,相当于记录下所有在数组中出现过的数字。对于[3, 5],has映射的内容是{3: true, 5: true}。这个映射的目的是为了后续快速判断一个数字是否在原始数组中出现过。 -
查找目标数字
代码从第四步确定的搜索起点(例如5)开始,逐个检查后续的正整数(5, 6, 7, ...)。对于每一个被检查的数字ans,它会在has映射中查找是否存在。如果has[ans]为true,说明该数字已在数组中出现过,则继续检查下一个数(ans++)。当找到第一个在has映射中找不到的数字(即has[ans]为false)时,这个数字就是我们要找的“大于平均值的最小未出现正整数”。对于例子[3, 5],检查过程是:数字5存在于映射中,继续;数字6不存在于映射中,因此找到目标数字6并返回。
复杂度分析
-
总的时间复杂度:O(n)。
这主要由两个连续的循环决定:第一个循环遍历数组以计算总和并构建映射,时间复杂度为 O(n)。第二个循环从平均值附近开始向上查找未出现的正整数。由于数组长度最多为100,且数字范围有限,这个查找循环在最坏情况下(例如数组包含了很多连续数字)的迭代次数也与n相关,可视为 O(n)。因此,总体时间复杂度是线性的 O(n)。 -
总的额外空间复杂度:O(n)。
代码使用了一个映射has来存储数组中出现过的所有数字。在最坏情况下,如果数组中的所有数字都不重复,这个映射需要存储 n 个键值对,因此额外空间复杂度为 O(n)。
Go完整代码如下:
package main
import (
"fmt"
)
func smallestAbsent(nums []int) int {
has := map[int]bool{}
sum := 0
for _, x := range nums {
has[x] = true
sum += x
}
ans := max(sum/len(nums)+1, 1) // 答案必须是正整数
for has[ans] {
ans++
}
return ans
}
func main() {
nums := []int{3, 5}
result := smallestAbsent(nums)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def smallest_absent(nums):
"""
返回最小的正整数,满足:
1. 不在数组 nums 中
2. 至少为 max(平均值 + 1, 1)
"""
if not nums:
return 1 # 处理空数组情况
has = set(nums)
total = sum(nums)
# 计算起始值:至少为平均值+1,且至少为1
ans = max(total // len(nums) + 1, 1)
# 如果起始值已存在,则递增直到找到不存在的值
while ans in has:
ans += 1
return ans
# 测试示例
if __name__ == "__main__":
test_cases = [
[3, 5], # 原示例
[1, 2, 3], # 平均值=2, 2+1=3但3存在,返回4
[-1, 0, 1], # 平均值=0, 0+1=1但1存在,返回2
[2, 2, 2, 2], # 平均值=2, 2+1=3,3不存在,返回3
[], # 空数组,返回1
[100, 200], # 平均值=150, 150+1=151,返回151
]
for nums in test_cases:
result = smallest_absent(nums)
print(f"smallest_absent({nums}) = {result}")
C++完整代码如下:
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
int smallestAbsent(const std::vector<int>& nums) {
if (nums.empty()) {
return 1; // 空数组返回1
}
std::unordered_set<int> has;
long long sum = 0; // 使用long long防止大数溢出
for (int x : nums) {
has.insert(x);
sum += x;
}
// 计算起始值:至少为平均值+1,且至少为1
int ans = std::max(static_cast<int>(sum / nums.size() + 1), 1);
// 如果起始值已存在,则递增直到找到不存在的值
while (has.find(ans) != has.end()) {
ans++;
}
return ans;
}
int main() {
// 测试用例
std::vector<std::vector<int>> testCases = {
{3, 5}, // 原示例
{1, 2, 3}, // 平均值=2, 2+1=3但3存在,返回4
{-1, 0, 1}, // 平均值=0, 0+1=1但1存在,返回2
{2, 2, 2, 2}, // 平均值=2, 2+1=3,3不存在,返回3
{}, // 空数组,返回1
{100, 200}, // 平均值=150, 150+1=151,返回151
{INT_MAX, INT_MAX} // 测试大数情况
};
for (const auto& nums : testCases) {
int result = smallestAbsent(nums);
std::cout << "smallestAbsent({";
for (size_t i = 0; i < nums.size(); i++) {
std::cout << nums[i];
if (i < nums.size() - 1) std::cout << ", ";
}
std::cout << "}) = " << result << std::endl;
}
return 0;
}