給定正整數數組,將所有數字拼接成一個數,求能拼接出的最小數字。例如 `{3, 32, 321} → 321323`。
輸入:多測試用例,每用例先給 n (1≤n≤100),再給 n 個正整數 (≤107)。
輸出:每用例輸出最小拼接數字。
**關鍵規則**:對任意兩數字串 `a`、`b`,若 `a+b < b+a`(字典序),則 `a` 應排在 `b` 前面。這保證最終拼接最小。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 100
#define MAX_LEN 10 // 10^7 最多 8 位,留餘量
char strs[MAX_N][MAX_LEN];
char cat_a[2*MAX_LEN], cat_b[2*MAX_LEN];
// 比較器:返回 <0 表示 a 排前面
int cmp(const void *a, const void *b) {
const char *sa = *(const char**)a;
const char *sb = *(const char**)b;
strcpy(cat_a, sa); strcat(cat_a, sb);
strcpy(cat_b, sb); strcat(cat_b, sa);
return strcmp(cat_a, cat_b);
}
int main() {
int n;
while (scanf("%d", &n) == 1 && n > 0 && n <= MAX_N) {
for (int i = 0; i < n; ++i) {
int x; scanf("%d", &x);
sprintf(strs[i], "%d", x);
}
// qsort 需要指針數組
char *ptrs[MAX_N];
for (int i = 0; i < n; ++i) ptrs[i] = strs[i];
qsort(ptrs, n, sizeof(char*), cmp);
// 輸出拼接
for (int i = 0; i < n; ++i) printf("%s", ptrs[i]);
printf("\n");
}
return 0;
}
// 原代碼核心邏輯
void bubbleSort(char c[][10], int n) {
for (int i = n-1; i > 0; --i)
for (int j = n-1; j > n-1-i; --j)
if (findSmall(c, j)) swap(c, j, j-1);
}
int findSmall(char c[][10], int i) {
// 比較 c[i] + c[i-1] vs c[i-1] + c[i]
// 字符串拼接後逐字符比較
}
優缺點:邏輯正確,但 O(n²) 在 n=100 時尚可(10⁴ 比較),`qsort` O(n log n) 更優。字符串拼接比較可直接用 `strcmp(strcat(a,b), strcat(b,a))`。
| 情況 | 處理 | 示例 |
|---|---|---|
| 前導零 | 輸入為正整數,無前導零 | {0, 0} 不合法 |
| 全零輸出 | 題目保證正整數,無全零 | 若允許 0,需特判輸出單個 0 |
| 超長拼接 | n=100, 每數 8 位 → 800 位,需大數輸出 | 直接 `printf("%s")` 逐段輸出 |
| 相等字符串 | 比較器返回 0,順序無關 | {12, 121} → 12112 |
| 輸入 | 輸出 | 說明 |
|---|---|---|
| 3 3 32 321 | 321323 | 經典示例 |
| 3 23 13 6 | 13236 | 13 < 23 < 6 (13236 < 13623...) |
| 2 23456 56 | 2345656 | 2345656 < 5623456 |
| 4 9 91 919 9191 | 9 91 919 9191 → 9919199191? | 實際排序:9, 91, 919, 9191 → 9919199191 |
本題核心是**識別拼接順序的自定義比較規則**:`a+b < b+a`。將數字轉字符串後按此規則排序,直接拼接即得最小值。工程中優先使用標準庫 `qsort`/`std::sort` 配合自定義比較器,代碼簡潔且性能優於手寫冒泡。注意大數輸出直接流式打印,避免溢出。