Online Compiler C

#include <stdio.h> #include <string.h> int main() { char str[20]; // 1. 读取输入的数字字符串 (不超过 10^10 对应最多 11 位数) if (scanf("%s", str) != 1) { return 0; } int len = strlen(str); int swapped = 0; // 2. 从左到右寻找最佳的交换位置 for (int i = 0; i < len - 1; i++) { int max_idx = i; // 在当前位置 i 的右侧寻找最大的数字 for (int j = i + 1; j < len; j++) { // 注意:当数字相同时,选择最右边(靠后)的那个,所以用 >= if (str[j] >= str[max_idx]) { max_idx = j; } } // 如果右侧的最大数字严格大于当前位置的数字,则进行交换 if (str[max_idx] > str[i]) { char temp = str[i]; str[i] = str[max_idx]; str[max_idx] = temp; swapped = 1; break; // 只能交换一次,完成即可退出 } } // 3. 输出最终结果并换行 printf("%s\n", str); return 0; }
这段代码的目标是:给定一个数字字符串,只允许交换其中两个数字一次,使得结果数字尽可能大。

代码的思路是:从左到右遍历每个位置,在它右侧找到最大的数字,如果这个最大数字比当前位置的数字大,就交换它们并结束。

这段代码有一个逻辑问题。当右侧有多个相同的最大数字时,代码选择最右边的一个(因为用了 `>=`)。但为了得到最大的结果,应该选择最右边的最大数字吗?不一定。考虑一个例子:数字 `1993`,如果交换第一位 `1` 和右侧最大的数字 `9`,应该交换哪个 `9`?交换第一个 `9` 得到 `9193`,交换最后一个 `9` 得到 `9193`,结果一样。但如果是 `1929`,交换第一位 `1` 和右侧最大的数字 `9`,应该交换哪个 `9`?交换第一个 `9` 得到 `9129`,交换最后一个 `9` 得到 `9129`,结果一样。似乎没问题。但考虑 `1299`,交换第一位 `1` 和右侧最大的数字 `9`,选择最右边的 `9` 得到 `9291`,选择左边的 `9` 得到 `9291`,结果一样。所以这个选择似乎不影响。

但有一个更隐蔽的问题:当当前位置的数字和右侧最大数字相等时,代码不会交换(因为条件 `str[max_idx] > str[i]` 不成立)。这没问题,因为交换相等的数字没有意义。但代码在寻找最大数字时用了 `>=`,这导致当右侧有多个相同最大数字时,`max_idx` 指向最右边的一个。这本身不是错误,但可能影响后续判断。

真正的问题在于:代码只考虑了一次交换,但题目要求只交换一次,这没问题。然而,代码的交换策略是“找到第一个可以交换的位置就交换并结束”,这不一定能得到全局最大的结果。例如,数字 `98321`,第一位 `9` 已经是最大,不会交换;第二位 `8` 右侧最大是 `3`,但 `8 > 3`,不交换;第三位 `3` 右侧最大是 `2`,不交换;第四位 `2` 右侧最大是 `1`,不交换。最终没有交换,但原数字已经是最大。这没问题。

但考虑 `132`,