一次遍历即可求解:初始化最小值为首个元素,差值为INT_MIN,从索引1开始遍历,每步用当前元素减已遍历部分最小值更新最大差,再更新最小值;需特判空数组和单元素数组。

直接用一次遍历就能搞定,不需要排序
排序会让时间复杂度升到 O(n log n),而最大差值只依赖最小值和最大值的位置关系:必须是“后面元素减前面元素”,所以不能简单取全局最大减最小。正确做法是一边扫一边记下已遍历部分的最小值,再用当前元素减它,更新最大差值。
常见错误是写成 max(arr) - min(arr),这忽略了“前小后大”的顺序约束;或者双重循环暴力比对,O(n²) 在 n > 10⁵ 时明显卡顿。
- 遍历从索引
1开始(第一个元素设为初始最小值) - 每步先算
arr[i] - min_so_far,再更新min_so_far = min(min_so_far, arr[i]) - 注意初始化:差值初值设为
INT_MIN或arr[1] - arr[0],避免全负数组返回 0
用 std::min_element 和 std::max_element 会出错
这两个函数只返回迭代器,不保证相对位置——std::max_element 可能在 std::min_element 左侧,导致差值为负或逻辑错乱。它们适合求无序极值,但不适用本题的“前小后大”约束。
有人试图分段:先找最小值位置 i,再在 [i+1, end) 找最大值,这看似合理,但漏掉了更优解——比如最小值出现在中间,而最大值在其左侧、但某个更靠右的次小值搭配更右侧的大值能产生更大差值(例:[5, 2, 3, 1, 8],最小值 1 在索引 3,右侧无元素;但 2(索引1)和 8(索引4)差为 6,才是答案)。
立即学习“C++免费学习笔记(深入)”;
边界情况必须手动检查
空数组、单元素数组没有合法的“两个元素”差值,应提前返回错误标识(如抛异常或返回 std::nullopt)。若题目允许非正差值(如全递减),需确认是否要求“至少一个正差”,否则最大差可能为负——这时仍按算法走,只是初值不能硬设为 0。
if (arr.size() 必须拦截- 用
long long存结果,防止int溢出(如arr[i]=INT_MAX,min_so_far=INT_MIN) - 如果数组含
NaN或自定义类型,需重载比较逻辑,标准min不适用
C++17 结构化绑定让代码更干净
不用手写索引变量,用结构化绑定配合 std::minmax_element 并不行(原因见上),但可以封装成简洁的一次遍历:
int maxDifference(const std::vector<int>& arr) {
if (arr.size() < 2) throw std::invalid_argument("size < 2");
int min_so_far = arr[0];
int max_diff = arr[1] - arr[0];
for (int i = 1; i < arr.size(); ++i) {
max_diff = std::max(max_diff, arr[i] - min_so_far);
min_so_far = std::min(min_so_far, arr[i]);
}
return max_diff;
}
这个版本没隐藏状态,每步语义清晰;若需返回下标而非值,把 min_so_far 换成 min_idx,同步更新即可。别为了“函数式风格”强行用 std::accumulate,可读性和调试成本会上升。
最容易被忽略的是:题目没说数组非空,也没说元素可比较,实际工程中得加 static_assert 或概念约束,否则模板实例化失败时错误信息极不友好。


















