1. 题目解析与解题思路
这道题目要求我们判断一个三位数中是否有且仅有两个相同的数字。换句话说,我们需要检查输入的数字是否是"双胞胎数"(如112、121、211等),同时排除像111这样的全相同数字和123这样所有数字都不同的情况。
1.1 题目理解要点
首先我们需要明确几个关键点:
- 输入保证是一个三位正整数
- 需要判断的是数字的组成,而不是数值本身
- 只有恰好两个相同数字的情况才输出"Yes"
- 三个数字全相同或全不同都输出"No"
1.2 解题核心思路
解决这个问题的基本思路可以分为三个步骤:
- 分解数字:将三位数的每一位数字提取出来
- 比较数字:检查这些数字之间的相等关系
- 判断条件:统计相同数字的对数,当且仅当有一对时输出"Yes"
2. 代码实现详解
2.1 数字分解的实现
c复制int str[3] = {0};
int n = 0;
scanf("%d", &n);
for(int i = 0; i < 3; i++) {
str[i] = n % 10;
n /= 10;
}
这段代码完成了数字分解的工作:
- 定义一个长度为3的数组
str来存储各位数字 - 使用
n % 10获取最低位的数字 - 通过
n /= 10去掉已经处理的最低位 - 循环3次即可得到所有位上的数字
注意:这里数字的存储顺序是从个位到百位,即str[0]是个位,str[1]是十位,str[2]是百位。这种顺序不会影响后续的比较结果。
2.2 数字比较的实现
c复制int cnt = 0;
for(int i = 0; i < 3; i++) {
for(int o = i + 1; o < 3; o++) {
if(str[i] == str[o]) {
cnt++;
}
}
}
这段代码通过双重循环比较数字:
- 外层循环遍历每个数字
- 内层循环从当前数字的下一个开始比较
- 当发现相等时计数器
cnt加1
这种比较方式确保每对数字只比较一次,不会重复比较。
2.3 条件判断的实现
c复制if(cnt == 1) {
printf("Yes");
} else {
printf("No");
}
这是最后的判断逻辑:
- 当
cnt == 1时,说明有且仅有一对数字相同,输出"Yes" - 其他情况(0对或3对)都输出"No"
3. 算法分析与优化
3.1 时间复杂度分析
该算法的时间复杂度是O(1),因为:
- 数字分解的循环固定执行3次
- 数字比较的双重循环最多执行3次(3选2的组合数)
- 无论输入数字多大,执行步骤都是固定的
3.2 空间复杂度分析
空间复杂度也是O(1),只使用了固定大小的数组和几个变量。
3.3 可能的优化方案
虽然这个问题的规模很小,优化意义不大,但我们可以考虑以下改进:
- 提前终止比较:当发现cnt>1时可以直接终止循环
- 使用位运算:可以用位掩码来记录数字出现情况
- 数学方法:通过数字的数学特性直接判断
4. 常见问题与调试技巧
4.1 常见错误
- 数组越界:确保数组大小足够(必须是3)
- 数字分解错误:注意
%和/运算的顺序 - 比较逻辑错误:确保不会重复比较同一对数字
- 边界条件处理:如100、999等特殊情况
4.2 调试技巧
- 打印中间结果:在分解和比较后打印数组内容和cnt值
- 测试用例设计:
- 全相同数字:111
- 全不同数字:123
- 一对相同数字:112
- 包含0的数字:101
- 使用调试器:单步执行观察变量变化
5. 扩展思考
5.1 问题变种
- 判断n位数中是否有且仅有k个相同数字
- 统计数字中相同数字的对数
- 找出数字中重复的数字
5.2 其他实现方法
- 使用字符串处理:
c复制char str[4];
scanf("%s", str);
if((str[0]==str[1]) + (str[0]==str[2]) + (str[1]==str[2]) == 1)
printf("Yes");
else
printf("No");
- 使用数学方法:
c复制int a = n/100, b = (n/10)%10, c = n%10;
int cnt = (a==b) + (a==c) + (b==c);
if(cnt == 1) printf("Yes");
else printf("No");
6. 实际应用场景
这类数字判断问题在实际中有多种应用:
- 密码强度检测:检查是否有重复字符
- 游戏开发:如彩票号码、骰子结果的判断
- 数据校验:检查ID号等是否符合特定模式
7. 编程技巧总结
- 数字分解:
%10和/10的组合是处理数字位的常用技巧 - 组合比较:双重循环是处理两两比较的标准模式
- 条件统计:通过计数器实现精确条件判断
- 边界测试:特别注意全同、全异等边界情况
在实际编程中,我发现这类问题最重要的是理清判断条件和找到高效的比较方法。对于固定位数的问题,通常不需要考虑太复杂的算法,清晰易懂的代码更重要。