電話番号からアルファベット組み合わせを生成するアルゴリズム

問題概要:

数字文字列(2〜9のみ)を入力として、該当するすべてのアルファベット組み合わせを返す。結果は任意の順序で出力可能。

電話ボタンの数字とアルファベットの対応関係は以下の通り(1は対応なし):

2 -> "abc"
3 -> "def"
4 -> "ghi"
5 -> "jkl"
6 -> "mno"
7 -> "pqrs"
8 -> "tuv"
9 -> "wxyz"

例:input = "23"["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] を返す。

解法アプローチ:

本問題は「バックトラッキング(再帰的探索)」アルゴリズムを用いて解く。全ての可能性を網羅するタイプの問題に最適。

処理フロー

  1. 数字→文字の変換テーブルの構築
  • 数字と文字の対応関係をMap型で定義。
  • 例:2"abc"3"def"
  1. 再帰的探索の実装
  • 入力文字列の先頭から順に各数字に対応する文字を追加。
  • 現在の組み合わせをStringBufferで保持し、再帰呼び出し後に状態を戻す(バックトラック)。
  • 入力文字列の末尾に達した時点で、現在の組み合わせを結果リストに追加。
  1. 終了条件
  • 再帰の深さが入力文字列の長さに達した場合、組み合わせを確定。

コード実装:

class PhoneNumberCombinator {
    public List<String> generateCombinations(String inputDigits) {
        List<String> results = new ArrayList<>();
        if (inputDigits.isEmpty()) return results;

        // 数字と文字のマッピングテーブル
        Map<Character, String> digitMap = new HashMap<>();
        digitMap.put('2', "abc");
        digitMap.put('3', "def");
        digitMap.put('4', "ghi");
        digitMap.put('5', "jkl");
        digitMap.put('6', "mno");
        digitMap.put('7', "pqrs");
        digitMap.put('8', "tuv");
        digitMap.put('9', "wxyz");

        // 探索開始
        exploreCombinations(results, inputDigits, 0, digitMap, new StringBuffer());
        return results;
    }

    private void exploreCombinations(List<String> results, String inputDigits, int position, 
                                    Map<Character, String> digitMap, StringBuffer current) {
        // 終了条件:入力文字列の末尾に達した場合
        if (position == inputDigits.length()) {
            results.add(current.toString());
            return;
        }

        char currentDigit = inputDigits.charAt(position);
        String possibleChars = digitMap.get(currentDigit);

        for (int i = 0; i < possibleChars.length(); i++) {
            current.append(possibleChars.charAt(i));
            exploreCombinations(results, inputDigits, position + 1, digitMap, current);
            current.deleteCharAt(current.length() - 1); // バックトラック
        }
    }
}

実装詳細:

  1. generateCombinationsメソッド
  • 入力が空文字の場合、空リストを返却。
  • 数字と文字のマッピングテーブルを初期化。
  • 探索を開始するためexploreCombinationsメソッドを呼び出す。
  1. exploreCombinationsメソッド
  • positionは現在処理中の数字のインデックス。
  • 終了条件:positionが入力文字列の長さに等しい場合、現在の組み合わせをリストに追加。
  • 現在の数字に対応する文字を取得し、それぞれに対して再帰呼び出しを実行。
  • 再帰呼び出しから戻る際、最後に追加した文字を削除して状態を戻す(バックトラック)。

計算量評価:

  • 時間計算量O(4^n)(nは入力文字列の長さ、最大4文字の選択肢があるため)
  • 空間計算量O(n)(再帰スタックの深さ)+O(4^n)(結果リストのサイズ)

まとめ:

  • バックトラッキングアルゴリズムにより、すべての可能性を効率的に探索。
  • 再帰とバックトラックの技術を用いて、組み合わせの生成を実現。
  • 計算量は指数関数的だが、全組み合わせを求める問題には適した手法。

タグ: backtracking Recursion LeetCode Java

7月8日 21:49 投稿