深度优先搜索DFS + 剪枝 | 回溯:力扣77. 组合

1、题目描述:

深度优先搜索DFS + 剪枝 | 回溯:力扣77. 组合_第1张图片

2、题解:

方法1:深度优先搜索DFS + 剪枝(回溯 + 剪枝)
思路:

套用回溯的模板,每次从传入的数字到n开始遍历求解,做选择和撤销选择,典型的回溯问题。另外要加剪枝,
也就是在DFS中先判断传进来的start和之后的数字如果不够构成 k就剪枝。
可以画一个树的图
回溯算法框架:
    res = []
    def backtrack(路径,选择列表):
        做剪枝
        if 满足结束条件:
            res.append(路径)
            return
        for 选择 in 选择列表:
            做选择
            backtrack(路径,选择列表)
            撤销选择

解决一个回溯问题,实际上就是一个决策树的遍历过程:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        #DFS,回溯
        res = []
        def dfs(start,path): #start是枚举选择的起点 path是当前构建的路径(组合)
            if len(path) + n - start + 1 < k: #剪枝
                return 
            if len(path) == k:
                res.append(path[:]) #拷贝一份path,推入res
                return              #结束当前递归
            for i in range(start,n+1): #枚举出所有选择
                path.append(i)          #选择
                dfs(i+1,path)           #向下继续选择
                path.pop()              #撤销选择
        dfs(1,[])
        return res

C++实现:

class Solution {
public:
    void dfs(int start,int n,int k,vector<int>& path,vector<vector<int>>&res){//start是枚举选择的起点 path是当前构建的路径(组合)
        if (path.size() + n - start + 1 < k){ //剪枝
            return;
        }
        if (path.size() == k){
            res.push_back(path); //拷贝一份path,推入res
            return;		//结束当前递归
        }
        for (int i = start;i <= n;i++){ //枚举出所有选择
            path.push_back(i);		//选择
            dfs(i+1,n,k,path,res);	//向下继续选择
            path.pop_back();		//撤销选择
        }
    }
    vector<vector<int>> combine(int n, int k) {
        // DFS,回溯
        vector<int> path;
        vector<vector<int>> ans;
        dfs(1, n, k,path,ans);
        return ans;        
    }
};

3、复杂度分析:

在这里插入图片描述

你可能感兴趣的:(LeetCode高频面试题)