如何实现无需过多条件判断的等差数列异常值查找程序?
解决等差数列异常值查找问题
嘿,我来帮你搞定这个问题!先看看你当前代码里的几个关键问题:
原代码的问题
排序破坏了原序列的核心信息
你给的例子[2,3,6,4,5]排序后变成[2,3,4,5,6],所有相邻差都是1,完全找不到原本的异常值6——这是因为排序把异常值放到了它在等差数列里的正确位置,直接让你的判断逻辑失效。等差数列的异常值是存在于原序列中的,排序操作完全没必要,反而帮了倒忙。数组越界风险
你的循环条件是i < orderSequence.Length,当i等于数组最后一个索引时,orderSequence[i+1]会直接超出数组范围,抛出IndexOutOfRangeException。判断逻辑不严谨
当遇到第一个不同的差时直接返回,但如果异常值在第二个位置(比如序列[5,2,3,4,5]),你的判断i > 1 ? ... : orderSequence[i-1]会访问i-1 = -1,同样触发越界异常。
改进后的解决方案
既然题目保证只有一个异常值,我们可以通过分析相邻差来找到它,不需要复杂的条件判断,思路如下:
- 计算所有相邻元素的差值,得到差数组。
- 确定正确的公差:因为只有一个异常值,正确公差是差数组中出现次数最多的那个(要么是
n-2次,要么是n-3次,取决于异常值在中间还是两端)。 - 找到第一个不符合正确公差的差值,根据它的位置判断异常值:
- 如果异常差值在开头:检查第二个差值是否正确,来判断是第一个元素还是第二个元素异常。
- 如果异常差值在结尾:直接判定最后一个元素是异常值。
- 如果异常差值在中间:要么是当前差值对应的后一个元素异常,要么是连续两个异常差值中间的元素异常(这是异常值在中间时的典型情况)。
最终代码
public int FindException(int[] sequence) { if (sequence.Length < 3) throw new ArgumentException("序列长度必须至少为3,否则无法判断异常值"); // 计算所有相邻元素的差值 var differences = new List<int>(); for (int i = 0; i < sequence.Length - 1; i++) { differences.Add(sequence[i + 1] - sequence[i]); } // 找到出现次数最多的公差(即正确公差) int correctDiff = differences.GroupBy(d => d) .OrderByDescending(group => group.Count()) .First() .Key; // 找到第一个不符合正确公差的差值索引 int abnormalDiffIndex = differences.FindIndex(d => d != correctDiff); // 根据异常差值的位置判断异常值 if (abnormalDiffIndex == 0) { // 第一个差值异常:如果第二个差值正确,说明第一个元素异常;否则第二个元素异常 return differences[1] == correctDiff ? sequence[0] : sequence[1]; } else if (abnormalDiffIndex == differences.Count - 1) { // 最后一个差值异常:说明最后一个元素异常 return sequence[sequence.Length - 1]; } else { // 中间差值异常:如果下一个差值也异常,说明中间元素异常;否则当前差值的后一个元素异常 return differences[abnormalDiffIndex + 1] != correctDiff ? sequence[abnormalDiffIndex + 1] : sequence[abnormalDiffIndex + 1]; } }
测试你的例子
输入[2,3,6,4,5]:
- 差数组为
[1,3,-2,1] - 正确公差是出现次数最多的
1 - 第一个异常差值索引是
1(差值为3) - 下一个差值
-2也不等于正确公差,所以返回中间元素sequence[2]即6,完全符合预期。
其他测试场景
- 异常值在开头:
[5,2,3,4,5]→ 返回5 - 异常值在结尾:
[2,4,6,8,11]→ 返回11 - 异常值在中间:
[3,5,7,11,13]→ 返回11
内容的提问来源于stack exchange,提问作者SarahB
相关产品推荐
相关产品推荐

