2025-06-19:识别数组中的最大异常值。用go语言,你有一个长度为 n 的整数数组 nums,其中恰好有 n-2 个元素属于“特殊数字”类别。剩下的两个元素中,一个等于所有这些特殊数字的总和,另一个是一个“异常值”。
这里,“异常值”的意思是:它既不是数组中那些特殊数字,也不是所有特殊数字的和。
题目要求特殊数字、和、异常值对应的索引互不相同(位置不同),但它们的数值可以相同。
需要你找出数组中可能的最大“异常值”。
3 <= nums.length <= 100000。
-1000 <= nums[i] <= 1000。
输入保证 nums 中至少存在 一个 可能的异常值。
输入: nums = [2,3,5,10]。
输出: 10。
解释:
特殊数字可以是 2 和 3,因此和为 5,异常值为 10。
题目来自力扣3371。
解决思路
我们需要找到一个“异常值” y,满足以下条件:
- 存在
n-2个“特殊数字”,它们的和为s。 - 数组中有一个元素等于
s(“和”)。 - 另一个元素
y是“异常值”,即y不等于s,且y不是任何“特殊数字”。 - 我们需要找到所有可能的
y中的最大值。
具体步骤
-
遍历所有可能的“和”候选:
- 对于数组中的每一个元素
y,假设y是“异常值”,那么剩下的n-1个元素中:- 有
n-2个“特殊数字”。 - 有
1个“和”(即这些特殊数字的和)。
- 有
- 我们需要检查是否存在这样的“和”
s满足:s是剩下的n-1个元素中的某一个。s等于其他n-2个“特殊数字”的和。
- 具体来说:
- 对于当前假设的“异常值”
y,计算剩余n-1个元素的总和total - y。 - 因为“特殊数字”有
n-2个,它们的和是s,所以total - y = s + s(因为“和”s也是剩下的n-1个元素之一)。 - 因此,
s = (total - y) / 2。 - 我们需要检查:
(total - y)是否能被2整除(即s是整数)。s是否存在于剩下的n-1个元素中(即s是“和”)。y不能是“特殊数字”或“和”(即y != s且y不是“特殊数字”)。- 但题目允许数值相同,只要索引不同即可,所以
y可以和s或“特殊数字”数值相同,只要位置不同。
- 对于当前假设的“异常值”
- 对于数组中的每一个元素
-
验证“和”
s的存在性:- 对于每个
y,计算s = (total - y) / 2。 - 检查
s是否在数组中:- 如果
s在数组中,且(total - y)是偶数,则y可能是“异常值”。 - 需要确保
s和y的索引不同(题目已保证)。
- 如果
- 对于每个
-
统计频率以优化检查:
- 使用哈希表(如
map)统计每个数字的频率。 - 对于每个
y:- 计算
t = (total - y)。 - 如果
t是偶数,则s = t / 2。 - 检查
s是否在哈希表中:- 如果
s就是y,则需要s出现至少2次(因为y和s需要是不同的索引)。 - 如果
s不是y,则需要s出现至少1次。
- 如果
- 计算
- 如果满足条件,则
y是一个可能的“异常值”。
- 使用哈希表(如
-
收集所有可能的“异常值”并取最大值:
- 遍历数组,按照上述方法收集所有可能的
y。 - 返回其中最大的
y。
- 遍历数组,按照上述方法收集所有可能的
时间复杂度和空间复杂度
- 时间复杂度:
- 遍历数组计算
total:O(n)。 - 构建哈希表
cnt:O(n)。 - 遍历数组检查每个
y:O(n)。 - 每次检查
s是否在哈希表中:O(1)。 - 总时间复杂度:
O(n)。
- 遍历数组计算
- 空间复杂度:
- 哈希表
cnt存储n个元素的频率:O(n)。 - 其他变量(如
total、ans等):O(1)。 - 总空间复杂度:
O(n)。
- 哈希表
总结
- 算法通过遍历数组两次(一次计算总和,一次检查“异常值”)和哈希表查询,高效地找到最大“异常值”。
- 时间复杂度和空间复杂度均为
O(n),适用于题目给定的约束条件。
Go完整代码如下:
.
package main
import (
"fmt"
"math"
)
func getLargestOutlier(nums []int) int {
cnt := map[int]int{}
total := 0
for _, x := range nums {
cnt[x]++
total += x
}
ans := math.MinInt
for _, y := range nums {
t := total - y*2
if cnt[t] > 1 || cnt[t] > 0 && t != y {
ans = max(ans, t)
}
}
return ans
}
func main() {
nums := []int{2, 3, 5, 10}
fmt.Println(getLargestOutlier(nums))
}
Python完整代码如下:
.
# -*-coding:utf-8-*-
def get_largest_outlier(nums):
from collections import Counter
cnt = Counter(nums)
total = sum(nums)
ans = float('-inf')
for y in nums:
t = total - 2 * y
if cnt[t] > 1 or (cnt[t] > 0 and t != y):
ans = max(ans, t)
return ans
if __name__ == "__main__":
nums = [2, 3, 5, 10]
print(get_largest_outlier(nums))