1 条题解
-
0
以下是针对这道题的题解:
题目分析
- 目标:对于给定的由小写字母组成的字符串(识别码),如果存在后继识别码,则输出后继识别码;如果给定的识别码是该组字符序列中的最后一个,则输出 “No Successor”。
- 输入数据:
- 输入由一系列行组成,每行包含一个表示识别码的字符串。
- 整个文件将由一行仅包含单个
#
的行来终止。
- 输出数据:
- 对于读取的每个识别码,输出包含一行,该行包含后继识别码或 “No Successor” 字样。
- 规则:
- 识别码由最多50个小写字母组成,可能包含重复字符。
- 后继识别码是在给定字符集的所有可能排列中,按字母顺序排在当前识别码之后的下一个识别码。
解题思路
- 读取输入:
- 使用
fgets
函数读取输入的每一行字符串,并去除行末的换行符。 - 如果读取到的字符串为
#
,则终止程序。
- 使用
- 判断是否存在后继识别码:
- 从字符串的末尾开始向前遍历,找到第一个顺序对
(s[i - 1], s[i])
,使得s[i - 1] < s[i]
。如果不存在这样的顺序对,则说明当前识别码是该组字符序列中的最后一个,输出 “No Successor”。
- 从字符串的末尾开始向前遍历,找到第一个顺序对
- 找到后继识别码:
- 从找到的位置
i
开始,在字符串的剩余部分中找到大于s[i - 1]
且最小的字符s[k]
。 - 交换
s[i - 1]
和s[k]
。 - 对字符串中从位置
i
开始的剩余部分进行升序排序,得到后继识别码。
- 从找到的位置
- 输出结果:
- 输出后继识别码。
代码实现
- 读取输入部分:
#include <iostream> #include <string> #include <cstring> #include <cstdio> #include <cstdlib> using namespace std; int cmp(const void *a, const void *b) { return *(char *)a - *(char *)b; } int main() { char s[60]; int i, j, sign, len; while (1) { if (fgets(s, sizeof(s), stdin) == NULL) { // 将 nullptr 替换为 NULL break; } len = strlen(s); if (len > 0 && s[len - 1] == '\n') { s[len - 1] = '\0'; } len = strlen(s); if (len == 1 && s[0] == '#') { break; } sign = 0; for (i = len - 1; i >= 1; i--) { if (s[i - 1] < s[i]) { sign = 1; break; } } if (sign == 0) { printf("No Successor\n"); } else { char ma = 120; int k; for (j = i; j < len; j++) { if (s[j] < ma && s[j] > s[i - 1]) { ma = s[j]; k = j; } } char m = s[i - 1]; s[i - 1] = s[k]; s[k] = m; qsort(&s[i], len - i, sizeof(char), cmp); for (j = 0; j < len; j++) { printf("%c", s[j]); } printf("\n"); } } return 0; }
复杂度分析
- 时间复杂度:
- 对于每个输入字符串,判断是否存在后继识别码的时间复杂度为(O(n)),其中(n)是字符串的长度。
- 找到后继识别码的时间复杂度为(O(n))。
- 对字符串的剩余部分进行排序的时间复杂度为(O(n \log n))。
- 因此,总的时间复杂度为(O(n \log n))。
- 空间复杂度:
- 主要的空间消耗在于存储输入的字符串,空间复杂度为(O(n)),其中(n)是字符串的长度。
- 1
信息
- ID
- 147
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者