算法D25 | 回溯算法2 | 216.组合总和III 17.电话号码的字母组合

本文介绍了如何使用回溯算法解决LeetCode中的两个问题,分别是组合总和III(216题)和电话号码的字母组合(17题),重点在于理解剪枝操作以及在Python和C++中的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

216.组合总和III 

如果把 组合问题理解了,本题就容易一些了。 

题目链接/文章讲解:代码随想录

视频讲解:和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III_哔哩哔哩_bilibili

本题和77组合 类似,剪枝操作根据sum<0来判断(前提是i>0且target_sum>0)。

Python:

class Solution:
    def __init__(self):
        self.result = []
        self.path = []

    def backtracking(self, k, n, start_idx):
        if n<0: return # 剪枝
        if len(self.path)==k:
            if n==0: self.result.append(self.path[:])
            return
        for i in range(start_idx, 9-(k-len(self.path))+2): #剪枝
            self.path.append(i)
            self.backtracking(k, n-i, i+1)
            self.path.pop()
        return

    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        self.backtracking(k, n, 1)
        return self.result
     

C++:

C++版本代码有点问题,某些情况下会超时。

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int k, int n, int startIdx) {
        if (n<0) return; //剪枝
        if (path.size()==k) { //终止条件
            if (n==0) result.push_back(path);
            return;
        }
        for (int i=startIdx; i<=9-(k-path.size())+1; i++) {
            path.push_back(i);
            backtracking(k, n-i, i+1); //回溯
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(k, n, 1);
        return result;    
    }
};

17.电话号码的字母组合 

本题大家刚开始做会有点难度,先自己思考20min,没思路就直接看题解。 

题目链接/文章讲解:代码随想录

视频讲解:还得用回溯算法!| LeetCode:17.电话号码的字母组合_哔哩哔哩_bilibili

Python版本:

N叉树的遍历,不涉及剪枝,需要穷举所有的组合即可。

class Solution:
    def __init__(self):
        self.letter_map = {
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz"
        }        
        self.result = []
        self.path = []
    
    def backtracking(self, digits, idx):
        if idx == len(digits):
            s = "".join(self.path)
            self.result.append(s)
            return
        digit = digits[idx]
        letter_list = self.letter_map[digit]
        for i in range(len(letter_list)):
            self.path.append(letter_list[i])
            self.backtracking(digits, idx+1)
            self.path.pop()
        return

    def letterCombinations(self, digits: str) -> List[str]:
        if len(digits)==0: return self.result
        self.backtracking(digits, 0)
        return self.result

C++版本:

class Solution {
private:
    const string letterMap[10] = {
        "", //0
        "", //1
        "abc", //2
        "def", //3
        "ghi", //4
        "jkl", //5
        "mno", //6
        "pqrs", //7
        "tuv", //8
        "wxyz" //9
    };

public:
    vector<string> result;
    string s;
    void backtracking(const string& digits, int idx) {
        if (idx==digits.size()) {
            result.push_back(s);
            return;
        }
        int digit = digits[idx] - '0';
        string letters = letterMap[digit];
        for (int i=0; i<letters.size(); i++) {
            s.push_back(letters[i]);
            backtracking(digits, idx+1);
            s.pop_back();
        }

    }
    vector<string> letterCombinations(string digits) {
        if (digits.size()==0) return result;
        backtracking(digits, 0);
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值