C语言统计和为指定值的三元组数量时输出错误的问题
统计和为12的三元组:原代码错误原因与修改原理
原代码错误原因
你的原代码三个循环都从0开始遍历整个数组,这会导致同一个元素组合的所有排列都被重复计数:
- 比如三元组
(1,3,8),它的全排列有6种(3个元素的排列数为3! = 6),每种排列都会触发一次计数条件,被算成6个独立的结果。 - 你写的
arr[i] != arr[j] && arr[j] != arr[k]只能排除元素值重复的情况(比如两个1的情况),但无法区分"元素相同但顺序不同"的重复组合。
你的预期是统计不考虑顺序的唯一三元组,但原代码统计的是"所有顺序不同的三元组排列",6个有效组合×6种排列=36,正好是你得到的输出。
原代码:
#include <stdio.h> #include <stdlib.h> int main() { system("cls"); int count = 0; int arr[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { for (int k = 0; k < 8; k++) { if (arr[i] + arr[j] + arr[k] == 12 && arr[i] != arr[j] && arr[j] != arr[k]) { count = count + 1; } } } } printf("Count=%d", count); return 0; }
修改后代码的原理
把循环条件改为j = i + 1和k = j + 1,本质是强制三个索引满足严格递增的顺序:i < j < k:
- 每个元素组合只会被遍历一次,因为索引顺序固定,不会出现排列不同的情况。比如只会遍历到
i对应1、j对应3、k对应8的情况,不会出现i=1,j=8,k=3或其他排列。 - 这种方式直接避免了重复计数,统计的就是"不考虑顺序的唯一三元组",正好得到你预期的6个结果。
修改后的核心循环代码:
for (int i = 0; i < 8; i++) { for (int j = i + 1; j < 8; j++) { for (int k = j + 1; k < 8; k++) { if (arr[i] + arr[j] + arr[k] == 12) { count = count + 1; } } } }
(注:这里甚至可以去掉arr[i] != arr[j] && arr[j] != arr[k]的判断,因为i<j<k的索引顺序已经保证了数组中元素不会重复选取,而你的数组本身也没有重复元素)
你列出的重复组合示例也能验证这一点:正确的6个唯一三元组是1 3 8、1 4 7、1 5 6、2 3 7、2 4 6、3 4 5,剩下的都是这些组合的排列。
内容的提问来源于stack exchange,提问作者usedmoney
相关产品推荐
相关产品推荐

