バックトラックで 電話の ボタンの 数字から 作れる 文字の 並びを 全部集める
昔の
海外で定番の問題リスト 4 本には入っていません
問題
昔の
- 2 は
abc、3 は def、4 は ghi、5 は jkl - 6 は
mno、7 は pqrs、8 は tuv、9 は wxyz
押したdigits で
- 返す順は
辞書の 順です。 1 字目を 上の 割り 当ての 順 (た とえば 7 なら p、 q、 r、 s の 順) に 選び、 1 字目が 同じ物どうしは 2 字目を 同じ 決まりで選びます digitsが空なら、 空の 並び []を返しますdigitsの長さは 0 以上 4 以下で、 字は どれも "2"から"9"のどれかです
入力と出力の例
例 1
5 は j、
例 2
数字が 1 つなら、
例 3
何も
面接での聞かれ方
面接では、
- 「電話の
数字の 並びから、 作れる 文字の 組み合わせを 全部返してください」 - 書き終えると
「何通りに なりますか? 計算量は?」と、 答えの 数から 計算量を 言えるかを 聞かれます - 「再帰を
使わずに 書けますか?」と、 並びを 1 段ずつ 広げる 書き方を 聞かれる こともあります
空の[] を[""] を
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「再帰と木」に、
関わる学び
再帰は、
まず 考える手順
段 1
数字の
段 2
「i 桁目の
段 3
各桁では、
段 4
digits が[] を
解答
Python
Python
KEYS = {
"2": "abc", "3": "def",
"4": "ghi", "5": "jkl",
"6": "mno", "7": "pqrs",
"8": "tuv", "9": "wxyz",
}
def phone_letters(digits):
if not digits:
return []
out = []
def walk(i, s):
if i == len(digits):
out.append(s)
return
d = digits[i]
for c in KEYS[d]:
walk(i + 1, s + c)
walk(0, "")
return outJavaScript
JavaScript
const KEYS = {
2: "abc", 3: "def",
4: "ghi", 5: "jkl",
6: "mno", 7: "pqrs",
8: "tuv", 9: "wxyz",
};
function phoneLetters(digits) {
if (digits === "") {
return [];
}
const out = [];
const walk = (i, s) => {
if (i === digits.length) {
out.push(s);
return;
}
const d = digits[i];
for (const c of KEYS[d]) {
walk(i + 1, s + c);
}
};
walk(0, "");
return out;
}Go
Go
var keys = map[byte]string{
'2': "abc", '3': "def",
'4': "ghi", '5': "jkl",
'6': "mno", '7': "pqrs",
'8': "tuv", '9': "wxyz",
}
func phoneLetters(
digits string,
) []string {
out := []string{}
if digits == "" {
return out
}
var walk func(int, string)
walk = func(i int, s string) {
if i == len(digits) {
out = append(out, s)
return
}
d := digits[i]
for _, c := range keys[d] {
walk(i+1, s+string(c))
}
}
walk(0, "")
return out
}ここまでの
計算量
- 時間は O(4^n × n) です。
n は 数字の 数で、 1 つの 数字は 多くて 4 字なので 答えは 4^n 通りまで、 1 つを 作るのに n 字を つなぎます - 使う
記憶は、 答えを 除くと O(n) です。 再帰の 深さが n です。 答え その ものは O(4^n × n) あります
よく ある間違い
- 空の
入力で [""]を返す。 再帰に入る 前に 空を 確かめないと、 空の 文字列が 1 つ 入った 並びを 返します。 この 問題では []です - 7 と 9 を 3 字にする。 7 は
pqrs、9 は wxyzの 4 字です。割り 当ての 表を 書く ときに 1 字落とすと、 答えが 足りなくなります - 桁ごとに for を
入れ子にする。 入力の 長さで 入れ子の 深さが 変わるので、 決まった 数の for では 書けません - 選んだ字の
並びを 使い回して、 答えに 入れた あと 書き換える。 並び (Python の list や JavaScript の 配列) を 答えに そのまま 入れると、 あとの 書き換えで 中身が 変わります。 答えに 入れる ときは 文字列にします
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「桁の
数だけ選ぶ所が 続くので、 i 桁目の 字を 選んで i + 1 桁目へ 進む再帰にします。 全部の 桁を 選んだら 答えに 足します。 各桁で 割り 当ての字を 前から 試すので、 答えは 辞書の 順に 並びます。 空の 入力は 最初に 空の 並びを 返します。 答えは 4 の n 乗通りまでで、 時間は O(4^n × n) です。」
書き終えたら、
「例 1 の 58 では、
1 桁目に j を 選び、 2 桁目で t、 u、 v を 順に 足して jt、 ju、 jv です。 戻って 1 桁目を k に して kt、 ku、 kv、 次に l で lt、 lu、 lv、 全部で 9 通りです。」