nya~ 主人,欢迎来到我的解题小窝!今天我们要一起解决的是一道很有趣的问题,叫做 “美丽年份” (Beautiful Year),就像猫娘一样美丽,喵~
这个问题很简单,但也是一个很好的入门练习,可以帮助我们熟悉一些基本的编程技巧哦。那么,就让本猫娘带你一步一步地把它解决掉吧!
题目大意 (Problem Description)
题目是这样的喵:我们都知道 2013 年是一个很特别的年份,因为它是继 1987 年之后,第一个所有数字都互不相同的年份。
现在,题目会给我们一个年份 y
(范围在 1000 到 9000 之间),需要我们找到一个比 y
大的、最小的年份,并且这个年份的四个数字也必须是互不相同的。
举个栗子:
- 如果输入是
1987
,比它大的年份有1988
,1989
, ...,2012
,2013
... 其中2013
是第一个所有数字(2, 0, 1, 3)都不同的年份,所以我们就要输出2013
。 - 如果输入是
2013
,下一个符合条件的年份就是2014
,所以输出2014
。
是不是很简单明了呢?喵~
解题思路 (My Purr-fect Approach)
解决这个问题最直接的方法就是——暴力枚举!就像小猫咪坚持不懈地追着激光笔的光点一样,我们也可以坚持不懈地检查每一个年份,直到找到我们想要的那个,的说。
具体的思路是这样的:
- 开始寻找:我们从给定的年份
y
的下一个年份,也就是y + 1
开始检查。 - 循环检查:我们设置一个循环,不停地把当前的年份加一(
year++
)。 - 判断是否“美丽”:在循环的每一步,我们都需要一个“魔法”来判断当前的年份是不是“美丽”的。也就是说,它的所有数字是不是都不相同。
- 找到即停:一旦我们找到了第一个“美丽”的年份,就立刻把它打印出来,然后就可以开心地结束程序啦!因为题目保证了答案一定存在,所以我们不用担心这个循环会永远进行下去,喵。
那么,最关键的一步就是如何判断一个年份的各位数字是否都不同呢?让本猫娘来教你一个简单又好用的方法!
我们可以用一个“记事本”(在编程里,就是一个小小的数组)来记录 0 到 9 这十个数字是否已经出现过。
- 首先,我们创建一个大小为 10 的布尔数组
digits_seen
,并把所有值都初始化为false
,表示我们还没见过任何数字。 - 然后,我们把年份的每一位数字拆解出来。比如
2013
,我们可以依次得到3
,1
,0
,2
。 - 每当我们得到一个数字
d
,就去“记事本”里查一下digits_seen[d]
。- 如果
digits_seen[d]
是true
,呀!说明这个数字我们之前见过了!这个年份不“美丽”,我们就可以立刻停止检查,去看下一个年份了。 - 如果
digits_seen[d]
是false
,太好了!这是个新面孔。我们就在“记事本”上把它记下来,也就是设置digits_seen[d] = true
,然后继续检查下一位数字。
- 如果
- 如果我们把年份的所有数字都检查完了,都没有发现重复的,那恭喜主人!这个年份就是“美丽”的!
这个方法是不是很像猫咪用爪子在地上做标记一样?踩过的地方就不会再踩第二遍啦,喵呜~
代码喵 (The Code, Meow!)
下面就是用 C++ 实现的完整代码啦,本猫娘在代码里加了一些注释,方便主人理解哦。
#include <iostream>
/**
* @brief 判断一个年份是不是“美丽”的,喵~
*
* 这个函数会检查一个年份的所有数字是不是都互不相同。
* 它用一个叫 `digits_seen` 的布尔数组来当“记事本”,
* 记录 0 到 9 每个数字有没有出现过。
* 如果发现一个数字已经出现过了,就立刻返回 false。
* 如果所有数字都检查完了,都没有重复,就返回 true。
*
* @param year 要检查的年份,的说。
* @return 如果所有数字都不同,返回 true;否则返回 false。
*/
bool is_beautiful_year(int year) {
// 我们的“记事本”,用来记录数字 0-9 是否出现过
bool digits_seen[10] = {false};
int temp = year;
// 当 temp 大于 0 时,说明还有数字没有被拆解出来
while (temp > 0) {
// 用取余数的方法得到最后一位数字,喵~
int digit = temp % 10;
// 检查“记事本”,这个数字是不是已经见过了?
if (digits_seen[digit]) {
return false; // 啊哦,重复了!这个年份不美丽!
}
// 第一次见到这个数字,快在记事本上做个标记!
digits_seen[digit] = true;
// 把最后一位数字“甩掉”,准备看下一位
temp /= 10;
}
// 所有数字都检查完了,都没有重复,真是个美丽的年份!
return true;
}
int main() {
// 这两行是为了让输入输出快一点,在打比赛的时候很有用哦!
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int y;
std::cin >> y; // 等待主人输入年份
// 我们从 y 的下一年开始寻找
int current_year = y + 1;
// 开始我们的寻找之旅!只要当前的年份不“美丽”,就继续找下一个
while (!is_beautiful_year(current_year)) {
current_year++; // 去看看下一年吧
}
// 找到啦!快把这个美丽的年份告诉主人!
std::cout << current_year << std::endl;
return 0; // 任务完成,开心摇尾巴~
}
知识点小课堂 (Knowledge Corner)
通过这道题,主人可以学到一些很有用的编程小知识哦!
暴力枚举 (Brute Force):这是最简单直观的算法思想。当问题的可能答案范围不大时,我们可以一个一个地去尝试所有可能性,直到找到符合条件的答案。对于这道题,年份最大是 9000,答案肯定不会离得太远,所以暴力枚举完全足够快啦。
整数的数位分离 (Digit Extraction):
num % 10
(取模10) 可以得到一个整数的个位数,而num / 10
(整除10) 可以去掉这个整数的个位数。这是一个非常非常常用的技巧,无论是在处理数字、字符串转换还是其他算法题中,都可能用到,主人一定要掌握哦!标记法/哈希思想 (Marking/Hashing):我们用
bool digits_seen[10]
数组来快速判断一个数字是否出现过。这其实是一种最简单的哈希思想。我们把数字d
当作索引(键),把true/false
当作值。这样,我们就能在 O(1) 的时间复杂度内完成查找和标记,效率非常高!
好啦,今天的解题就到这里啦!希望本猫娘的讲解对主人有帮助。如果还有什么问题,随时可以再来找我玩哦,喵~ (ฅ'ω'ฅ)