常见错误是内层循环误用i而非j,如arrayB[i]应为arrayB[j],导致越界或逻辑错误。

双重 for 循环遍历时 i 和 j 顺序搞反了
常见错误是写成 for(int i = 0; i ,这会把 <code>(i,j) 和 (j,i) 当作两组不同元素处理,比如 (1,2) 和 (2,1) 都算一次——实际只需一次。
正确做法是让内层循环起点严格大于外层索引:
- 要无序配对(如计算所有不重复的元素对),用
for(int j = i + 1; j - 若需包含自身配对(如
(i,i)),则用for(int j = i; j - 绝对不要用
j = 0开始,除非你明确需要全排列(含顺序、含自身)
用 set> 临时去重太重了
有人为保险起见,在循环里把 make_pair(min(i,j), max(i,j)) 插入 set 再判断是否已存在,这在 n=1000 时就明显拖慢速度——set 插入是 O(log n),整个嵌套变成 O(n² log n),还占额外内存。
真正需要动态去重的场景极少,绝大多数情况靠索引约束就能解决。只有当你无法预知元素位置(比如从容器中随机取两个迭代器),才考虑用 unordered_set 配合自定义哈希,但务必先确认必要性。
立即学习“C++免费学习笔记(深入)”;
结构体数组或 vector 中元素地址相同但值不同怎么办
如果循环处理的是指针数组或 vector<T*>,即使 i != j,也可能出现 arr[i] == arr[j](指向同一对象)。这时仅靠索引去重不够。
此时应额外判断指针值:
-
if (i == j) continue;// 索引去重 -
if (arr[i] == arr[j]) continue;// 地址去重 - 如果语义上“值相等即视为重复”,那就用
if (arr[i] == arr[j] && i != j),注意重载operator==是否符合预期
break 或 goto 跳出多层循环时漏掉状态更新
当在嵌套循环中找到目标后用 goto 或标志位提前退出,容易忽略“这一对已被处理”的事实,导致外层继续迭代时又撞上同一对。
典型陷阱:
- 在内层发现
i=3, j=7满足条件,goto done;,但外层i还没自增,下次进入仍是i=3,而j从0重新开始,可能再次命中(3,7) - 正确做法:要么用
break配合标签(C++ 不支持带标签的break,所以得用goto),要么设found = true并在外层加if (found) break; - 更稳妥的是直接 return,尤其在函数内做查找时
嵌套循环里“重复处理同一对”问题,根子往往不在算法逻辑,而在索引边界和退出机制这两个最基础的地方。越想用数据结构兜底,越容易掩盖真正的控制流漏洞。


















