バックトラックで電話のボタンの数字から作れる文字の並びを全部集める

昔の携帯電話のボタンには、数字ごとに英字がいくつか割り当てられています。押した数字の並びから作れる英字の並びを、決まった順で全部集める練習です。

海外で定番の問題リスト 4 本には入っていません

問題

昔の携帯電話では、数字のボタンに次の英小文字が割り当てられていて、同じボタンで違う字を打てました。

  • 2 は abc、3 は def、4 は ghi、5 は jkl
  • 6 は mno、7 は pqrs、8 は tuv、9 は wxyz

押した数字の並びを文字列 digits で受け取ります。数字ごとに割り当ての字を 1 つずつ選んでつなげた文字列を、選び方の全部について集め、並びにして返す関数を書いてください。

  • 返す順は辞書の順です。1 字目を上の割り当ての順 (たとえば 7 なら p、q、r、s の順) に選び、1 字目が同じ物どうしは 2 字目を同じ決まりで選びます
  • digits が空なら、空の並び [] を返します
  • digits の長さは 0 以上 4 以下で、字はどれも "2" から "9" のどれかです

入力と出力の例

例 1

5 は j、k、l、8 は t、u、v です。3 かける 3 で 9 通りです。

digits = "58"
["jt", "ju", "jv", "kt", "ku", "kv", "lt", "lu", "lv"]

例 2

数字が 1 つなら、割り当ての字がそのまま 1 字ずつ並びます。9 は 4 字です。

digits = "9"
["w", "x", "y", "z"]

例 3

何も押していないので、作れる文字列はありません。

digits = ""
[]

面接での聞かれ方

面接では、短く次のように渡されることが多いです。

  • 「電話の数字の並びから、作れる文字の組み合わせを全部返してください」
  • 書き終えると「何通りになりますか? 計算量は?」と、答えの数から計算量を言えるかを聞かれます
  • 「再帰を使わずに書けますか?」と、並びを 1 段ずつ広げる書き方を聞かれることもあります

空の入力で [] を返すのか [""] を返すのかを最初に確かめておくと、端で迷いません。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「再帰と木」に、この型の要点を表とコードでまとめています。

再帰は、同じ形の小さい問題に分けて自分を呼ぶ書き方です。木の深さや、全部の組み合わせを数える問題で使います。

main.py
def phone_letters(digits: str) -> list[str]:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(phone_letters("58"))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します