17_電話號碼的字母組合

zeta186012發表於2024-09-07

17_電話號碼的字母組合

【問題描述】

給定一個僅包含數字 2-9 的字串,返回所有它能表示的字母組合。答案可以按任意順序返回。給出數字到字母的對映如下(與電話按鍵相同)。注意1不對應任何字母。

img

示例一:
輸入:digits = "23"
輸出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例二:
輸入:digits = ""
輸出:[]

示例三:
輸入:digits = "2"
輸出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是範圍 ['2', '9'] 的一個數字。

【演算法設計思想】

本題主要是用到了DFS,即深度優先搜尋的思想。在此我們需要搞清楚DFS的基本思想和虛擬碼是怎麼樣的。

DFS的演算法設計思想:一種用於遍歷或搜尋樹或圖的演算法。DFS的基本思想是從根節點開始(選擇某個搜尋起始節點),先儘可能深的搜尋樹的分支,如果到底了(即到達一個葉子節點或者當前節點沒有任何未訪問的子節點),就回溯到上一層,繼續儘可能深的搜尋其它未搜尋過的子節點,這個過程一直持續到所有的節點都被訪問過為止。

虛擬碼如下:

procedure DFS(G,V):
	make V as visited;
	for each w in G.adjacent(v) do //遍歷v的所有鄰接頂點
		ifw is not visited then
		DFS(G,w)//遞迴訪問w

我們可以把這個問題看成是一個搜尋的問題,在這裡,2對應abc,3對應def,我們只需要求其組合就可以了,本質上是一個樹形的結構,我們對這個樹進行DFS即可得到答案,所以透過本題我們要複習DFS這個知識點。

【演算法描述】

C++:

class Solution
{
public:
    // 儲存結果的容器
    std::vector<std::string> ans;

    // 字串對映陣列,對應數字鍵上的字母
    std::string strs[10] = {",", "", "abc", "def", "ghi", "jkl",
                            "mno", "pqrs", "tuv", "wxyz"};

    // 主要的方法,用於獲取電話號碼的字母組合
    std::vector<std::string> letterCombinations(std::string digits)
    {
        // 如果輸入的數字字串為空,則直接返回空的結果集
        if (digits.empty())
        {
            return ans;
        }

        // 從第一個數字開始深度優先搜尋
        dfs(digits, 0, "");
        
        // 返回所有可能的組合
        return ans;
    }

    // 深度優先搜尋 (DFS) 輔助方法
    void dfs(const std::string &digits, int idx, std::string combine)
    {
        // 當前索引等於輸入字串的長度時,說明已經處理完了一個完整的組合
        if (idx == digits.length())
        {
            // 將當前組合加入結果集中
            ans.push_back(combine);
            return;
        }

        // 獲取當前數字對應的字母字串
        const std::string &s = strs[digits[idx] - '0'];

        // 遍歷當前數字對應的字母字串
        for (size_t i = 0; i < s.length(); i++)
        {
            // 將當前字母新增到組合字串中
            combine.push_back(s[i]);

            // 遞迴地進行下一步搜尋
            dfs(digits, idx + 1, combine);

            // 回溯:移除最後一個字元,以便嘗試下一個字母
            combine.pop_back();
        }
    }
};

Java:

import java.util.ArrayList;
import java.util.List;

class Solution {

    // 儲存結果的容器
    private List<String> ans = new ArrayList<>();

    // 字串對映陣列,對應數字鍵上的字母
    private String[] strs = {",", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    // 主要的方法,用於獲取電話號碼的字母組合
    public List<String> letterCombinations(String digits) {

        // 如果輸入的數字字串為空,則直接返回空的結果集
        if (digits.isEmpty()) {
            return ans;
        }

        // 從第一個數字開始深度優先搜尋
        dfs(digits, 0, "");

        // 返回所有可能的組合
        return ans;
    }

    // 深度優先搜尋 (DFS) 輔助方法
    private void dfs(String digits, int idx, String combination) {
        // 當前索引等於輸入字串的長度時,說明已經處理完了一個完整的組合
        if (idx == digits.length()) {
            // 將當前組合加入結果集中
            ans.add(combination);  // 修改為 add 而不是 append
            return;
        }

        // 獲取當前數字對應的字母字串
        String s = strs[digits.charAt(idx) - '0'];  // 使用 charAt 獲得字元而不是使用索引

        // 遍歷當前數字對應的字母字串
        for (int i = 0; i < s.length(); i++) {
            // 將當前字母新增到組合字串中
            combination += s.charAt(i);  // 使用 += 新增字元

            // 遞迴地進行下一步搜尋
            dfs(digits, idx + 1, combination);

            // 回溯:移除最後一個字元,以便嘗試下一個字母
            combination = combination.substring(0, combination.length() - 1);  // 使用 substring 方法回溯
        }
    }
}

Python:

from typing import List

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        # 結果容器
        ans: List[str] = []
        
        # 字串對映字典,對應數字鍵上的字母
        strs = {
            ",": "",
            "": "",
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz"
        }

        # 如果輸入的數字字串為空,則直接返回空的結果集
        if not digits:
            return ans

        # 深度優先搜尋 (DFS) 輔助方法
        def dfs(digits: str, idx: int, combination: str):
            # 當前索引等於輸入字串的長度時,說明已經處理完了一個完整的組合
            if idx == len(digits):
                ans.append(combination)
                return
            
            # 獲取當前數字對應的字母字串
            s = strs[digits[idx]]

            # 遍歷當前數字對應的字母字串
            for i in range(len(s)):
                # 將當前字母新增到組合字串中
                combination += s[i]
                
                # 遞迴地進行下一步搜尋
                dfs(digits, idx + 1, combination)
                
                # 回溯:移除最後一個字元,以便嘗試下一個字母
                combination = combination[:-1]

        # 從第一個數字開始深度優先搜尋
        dfs(digits, 0, "")
        
        # 返回所有可能的組合
        return ans

相關文章