top1编程
← 返回题目
题解

连接数字

1 条题解

  • 0
    @ 2026-8-5 23:52:33

    P4671 连接数字(提高)

    解题思路

    第一步,打破"按大小排序"的思维定式。 这道题不能按数字大小直接排序!比如 7 和 13,7 虽然比 13 小,但连接时 7 要排在 13 前面,因为 713 比 137 大。正确的规则是:比较任意两个数 x 和 y,要看"x 接 y"和"y 接 x"哪个拼出来的数更大,谁大就让谁排前面。

    第二步,把数当成字符串。 数字的位数可能不一样,直接用整数比大小不方便。我们把每个数当作字符串存进结构体 Num 的 str 字段里,比较的时候把两个字符串拼起来再比较。

    第三步,写自定义比较函数。 cmp(x, y) 里先把 x.str 和 y.str 拼成 xFirst,把 y.str 和 x.str 拼成 yFirst,用 strcmp 比较两个拼接结果:如果 xFirst 更大,就让 x 排前面。sort 用这个规则排完,数组的顺序就是能连出最大数的顺序。

    第四步,拼接输出。 按排好的顺序,把每个数的字符串依次输出,连在一起就是最大的多位整数,末尾换行。

    想一想生活里的例子。 两个人比姓名接龙,要把两种顺序都拼出来比比看,哪个拼出来更大就选哪种。

    边界情况: 每个数可能很长,字符串数组要开大一些(50);比较时拼接的临时字符串也要够大(110),避免溢出。这个规则是一种"贪心"思想:每次比较都选局部最优的拼接顺序,最后整体拼出来就是最大的。

    参考代码

    // P4671 连接数字:把n个正整数连成一排,组成最大的多位整数
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    struct Num {
        char str[50]; // 存一个正整数(当作字符串)
    };
    
    bool cmp(const Num &x, const Num &y) {
        // 比较 x放前面 还是 y放前面 连出来更大
        char xFirst[110], yFirst[110];
        strcpy(xFirst, x.str);
        strcat(xFirst, y.str);
        strcpy(yFirst, y.str);
        strcat(yFirst, x.str);
        return strcmp(xFirst, yFirst) > 0; // x在前更大,则x排前面
    }
    
    Num nums[1005];
    
    int main() {
        int n;
        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> nums[i].str;
        }
        sort(nums, nums + n, cmp); // 排序
        for (int i = 0; i < n; i++) {
            cout << nums[i].str; // 依次连接输出
        }
        cout << endl;
        return 0;
    }
    

    复杂度分析

    排序 n 个数需要 O(n log n) 次比较,每次比较要拼接两个字符串并比较,假设每个数最长 L 位,单次比较是 O(L)。总时间复杂度 O(n log n × L)。本题 n 和 L 都不大,速度很快。空间上要开一个 O(n) 的字符串数组。

    • 1