← ブログ一覧

最大の数を作る - 数字断片をつなげるカスタム比較ソート - AlgoNote

最大の数ソートカスタム比較文字列コーディングテストAlgoNote

数字断片をつなげて最大の数を作る

小さなナンバープレート店を思い浮かべてください。箱には数字が刻まれた金属の断片があります: [3, 30, 34, 5, 9]。お客さんが「この断片を全部1列につなげて、作れる最大の番号を作ってください!」と言います。

断片をどんな順番でつなげれば最大の数になるでしょうか?


罠 — 「数値の大きさ順」は間違い

最初に思いつくのは「大きい数字から並べよう」です。数値の降順で並べると 34, 30, 9, 5, 33430953

もっともらしく見えますが、間違った答えです。正解は 9534330 です。

なぜでしょう? 934 より小さい数字ですが、先頭に 9 を置くと先頭の桁が9になり、全体の数がずっと大きくなります。つまり「断片の数値」ではなく「つなげたときにどちらが大きいか」が本当の基準なのです。

特に紛らわしいのが 330 です。どちらを前に置くべきでしょう?

  • 3 を前に: "3" + "30" = 330
  • 30 を前に: "30" + "3" = 303

330 > 303 なので、3が前に来るべきです。数値では30が大きいのに、つなげてみると3が先に来た方が大きい数になるのです。


核心アイデア — a+b vs b+a

ここでソートの発想が出てきます。2つの断片 a, b の順序を決めるとき、数値ではなくつなげた文字列を比較します。

  • a + bb + a より大きければ → a を前に
  • b + aa + b より大きければ → b を前に

この1行の比較ルールをソートの基準(comparator)として差し込むだけです。

なぜ文字列比較で正しい? a+bb+a常に同じ長さです(2つの断片を合わせた長さ)。長さが同じ2つの数の大小は先頭の桁から比べればよく、それがまさに文字列の辞書順比較と一致するからです。

いくつか実際に当ててみるとルールが手に馴染みます。

  • 5 vs 959 vs 95 → 95が大きいので 9が前
  • 34 vs 5345 vs 534 → 534が大きいので 5が前
  • 30 vs 343034 vs 3430 → 3430が大きいので 34が前

こう比較して降順に並べると断片の順は 9, 5, 34, 3, 30 になり、全部つなげると 9534330 — 正解です。

最後にもう一つだけ罠を。断片がすべて0なら([0, 0])、つなげた結果が "00" になりますが、答えは "0" 1つであるべきです。ソート後の先頭文字が '0' なら "0" だけを返せばきれいに解決します。

まとめると、こういう流れです。

1. すべての断片を文字列に変換する

2. a+b vs b+a の比較で降順ソートする

3. 並べた断片を順につなげる

4. 先頭が '0' なら "0" だけを返す


自分の目で確かめる

断片が a+b vs b+a の比較(黄)を経て位置を入れ替え(赤)、1マスずつ最終的な順序に確定(緑)していく全工程をステップ別の可視化で用意しました。各比較で "330" vs "303" のような文字列がどう勝負を決めるか一目で分かります。

👉 最大の数を作る — ステップ別の可視化で解法を見る

「なぜ30より3が先に来るの?」は文章だけだと紛らわしいですが、2つの文字列が並べて比較されるのを一度見れば、「つなげて大きい方が勝つのか」が一瞬で分かります。

最大の数を作る - 数字断片をつなげるカスタム比較ソート - AlgoNote - AlgoNote | 알고노트(AlgoNote)