day22 第七章 回溯算法part01

腾讯文档

理论基础

回溯三部曲 ≈ 递归三部曲

回溯比递归多了一层对状态的记录,如path,该状态只记录当前,通过回撤来消除下一层的东西。

回溯本质是暴力搜索,复杂度没有变化,只能通过剪枝来减小一些复杂度。

cpp 复制代码
void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

77. 组合

有未知层for,for写不出来,所以用回溯,也就是递归。

递归的每一层for就是我们想写的每一层for,用if(终止条件)控制循环层数。

回溯算法通过递归的方式来控制for循环的层数。

grammar:

vector push_back() & pop_back();

cpp 复制代码
class Solution {
public:
    void backtracing(int n, int k, int start_index, vector<vector<int>>& res, vector<int>& path){
        //终止条件
        if(path.size()==k){
            res.push_back(path);
            return;
        }

        for(int i=start_index;i<=n-k+path.size()+1;i++){
            path.push_back(i);
            backtracing(n,k,i+1,res,path);
            path.pop_back();
        }


    }

    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> result;
        vector<int> path;

        backtracing(n, k, 1, result, path);
        return result;
    }
};

216.组合总和III

跟77.组合问题不同的是:总和+1,9

剪枝不一定能剪掉每一个多余的枝。

剪枝1:if(sum>n)

剪枝2:i<=9-(k-(path.size()+1))和上一题一样

cpp 复制代码
class Solution {
public:
    void backtracing(int k, int n, int start_index, vector<vector<int>>& res, vector<int>& path, int sum){
        if(sum>n){
            return;
        }
        if(path.size()==k){
            if(sum==n){
                res.push_back(path);
            }
            return;
        }

        for(int i=start_index;i<=9-(k-(path.size()+1);i++){
            path.push_back(i);
            sum += i;
            backtracing(k,n,i+1,res,path,sum);
            sum -= i;
            path.pop_back();
        }

    }
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> result;
        vector<int> path;
        backtracing(k,n,1,result,path,0);
        return result;
        
    }
};

17.电话号码的字母组合

其实完全可以两层for,不用回溯这么麻烦。

这是不同集合的组合,之前是同一集合的组合。

grammar:

cpp里string可以用push_back(), pop_back(),也可以直接+

list小写,用{}

map的key,value用,隔开

cpp 复制代码
class Solution {
public:
    map<char, list<char>> tele = {
        {'2',{'a','b','c'}},
        {'3',{'d','e','f'}},
        {'4',{'g','h','i'}},
        {'5',{'j','k','l'}},
        {'6',{'m','n','o'}},
        {'7',{'p','q','r','s'}},
        {'8',{'t','u','v'}},
        {'9',{'w','x','y','z'}}
    };
    void backtracing(vector<string>& res,vector<char>& path,vector<char>& digits, int start_index){
        if(digits.size()==0){
            return;
        }
        if(digits.size()==path.size()){
            string s(path.begin(), path.end());
            res.push_back(s);
            return;
        }

        list<char> l = tele[digits[start_index]];
        for(char c:l){
            path.push_back(c);
            backtracing(res, path, digits, start_index+1);
            path.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        vector<string> result;
        vector<char> path;
        vector<char> v_digits(digits.begin(), digits.end());
        backtracing(result, path, v_digits, 0);
        return result;
    }
};
相关推荐
geats人山人海16 分钟前
数据结构第六章c语言 树的存储下二叉树的概念和存储
c语言·数据结构·算法
漂流瓶jz1 小时前
UVA-12627 奇怪的气球膨胀 题解答案代码 算法竞赛入门经典第二版
算法·图论·递归·aoapc·算法竞赛入门经典·uva·12627
jarvisuni1 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
kobesdu1 小时前
流形上的优化:SO(3)与SE(3)的广义加减法在FAST-LIO中如何简化状态估计
人工智能·算法·fastlio
白狐_7982 小时前
408 数据结构算法题 01:线性表暴力求解保分指南
java·数据结构·算法
乐观勇敢坚强的老彭2 小时前
C++信奥:开关门、开关灯问题
开发语言·c++·算法
冻柠檬飞冰走茶2 小时前
PTA基础编程题目集 7-31 字符串循环左移(C语言实现)
c语言·开发语言·数据结构·算法
Hi李耶2 小时前
【LeetCode】4-寻找两个正序数组的中位数
算法·leetcode·职场和发展
图灵机z2 小时前
【算法提高课】AcWing 1027. 方格取数 长期攻克提高课-day3(3/219)
算法
hans汉斯2 小时前
计算机科学与应用|改进MeanShift算法在智能监控视频中的应用研究
图像处理·人工智能·功能测试·深度学习·算法·音视频