leetcode刷题之回溯算法(组合问题)

回溯算法模板

回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是穷举的本质。
for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历

void backtracking(参数) 
{
    
    
	//终止条件
    if (终止条件) 
    {
    
    
        存放结果;
        return;
    }
//for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历
//这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。
    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) 
   {
    
    
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

在这里插入图片描述

组合

77组合

题目 难度:中等

class Solution {
    
    
public:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(int n,int k,int startindex)
    {
    
    
        //终止条件
        if(path.size()==k)
        {
    
    
            result.push_back(path);
            return;
        }
        //for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历
        //每个节点都是一个for循环
        for(int i=startindex;i<=n;i++)
        {
    
    
         	path.push_back(i);
            backtracking(n,k,i+1);//可以理解为在树形结构上沿着分支往下搜索的过程
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) 
    {
    
    
        backtracking(n, k, 1);
        return result;
    }
};

组合问题的剪枝

在这里插入图片描述
优化过程如下:

  1. 已经选择的元素个数:path.size();
  2. 还需要的元素个数为: k - path.size();
  3. [x,n]的path数组长度为n-x+1= k - path.size()
  4. 在集合n中最多从 n - (k - path.size()) + 1开始for遍历;
    为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。举个例子,n = 4,k = 3, 目前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2。也就是最多取到2这个位置,可以是组合[2, 3, 4]。

优化后的代码:

class Solution 
{
    
    
private:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int n, int k, int startIndex) 
    {
    
    
        if (path.size() == k) {
    
    
            result.push_back(path);
            return;
        }
         // 优化的地方
        for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) 
        {
    
    
            path.push_back(i); // 处理节点
            backtracking(n, k, i + 1);
            path.pop_back(); // 回溯,撤销处理的节点
        }
    }
public:
    vector<vector<int>> combine(int n, int k) 
    {
    
    
        backtracking(n, k, 1);
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/mabaizi/article/details/128783249