为何传入空数组时countInversions函数会陷入无限循环?
问题原因分析与解决方案
这个问题的核心坑点在于**std::vector::size()返回的是无符号整数类型size_t**,完全不是你直觉里的有符号整数!
具体为什么会无限循环?
当输入数组为空时,array.size()的值是0(类型是size_t,无符号)。此时你写的array.size() - 1会触发无符号整数的下溢行为:无符号数不能为负,所以0 - 1会被转换成size_t类型能表示的最大值(比如在64位系统上是18446744073709551615)。
而你的循环变量i是int类型(有符号整数),当比较i < array.size() - 1时,C++会把有符号的i隐式转换成无符号的size_t类型:
- 当
i从0开始递增,直到达到int的最大值后,再++i会触发有符号整数溢出(未定义行为,但通常会变成负数); - 负数转换成
size_t后会变成一个极大的正数,依然小于array.size() -1对应的那个超大值,循环条件永远为真,自然就陷入无限循环了。
修复方案
有几种简单的方式可以避免这个问题:
方案1:修改循环条件,避免无符号数减1
把外层循环的条件改成i + 1 < array.size(),这样就不会出现无符号数下溢的情况:
int countInversions(vector<int> array) { int inversionsCounter = 0; for (int i = 0; i + 1 < array.size(); ++i) for (int j = i + 1; j < array.size(); ++j) if (array[i] > array[j]) ++inversionsCounter; return inversionsCounter; }
方案2:先将size转为有符号整数(适合数组不大的场景)
提前把array.size()的结果转成int类型,后续用这个变量来做判断:
int countInversions(vector<int> array) { int inversionsCounter = 0; int n = static_cast<int>(array.size()); for (int i = 0; i < n - 1; ++i) for (int j = i + 1; j < n; ++j) if (array[i] > array[j]) ++inversionsCounter; return inversionsCounter; }
注意:如果数组的大小超过了
int能表示的最大值(比如在32位系统上超过2^31-1),这种转换会出问题,所以更推荐方案1。
方案3:用size_t作为循环变量类型
把i和j都声明为size_t类型,这样就不会有类型转换的问题,同时可以加个提前判断优化空数组的情况:
int countInversions(vector<int> array) { int inversionsCounter = 0; size_t n = array.size(); if (n < 2) return inversionsCounter; // 空数组或只有一个元素直接返回0 for (size_t i = 0; i < n - 1; ++i) for (size_t j = i + 1; j < n; ++j) if (array[i] > array[j]) ++inversionsCounter; return inversionsCounter; }
验证修改后的代码
运行你提供的main函数,修改后的代码会正确输出0,不会再陷入无限循环。
内容的提问来源于stack exchange,提问作者maverick.01
相关产品推荐
相关产品推荐

