hot100 -- 回溯(上)

目录

🍞科普

🌼全排列

[AC DFS](#AC DFS)

🚩子集

[AC DFS](#AC DFS)

🎂电话号码的字母组合

[AC DFS](#AC DFS)

🌼组合总和

[AC DFS](#AC DFS)


🍞科普

忘记 dfs 的,先看看这个👇

DFS(深度优先搜索)8种题型_dfs典型问题-CSDN博客

🌼全排列

46. 全排列 - 力扣(LeetCode)

AC DFS

++排列型枚举哦~++

vector 中 push_back 和 [] 下标访问是不一样的

push_back() 是往末尾加入元素,vector 大小会自动增加

而 [] 是直接改变 vector 某个位置的元素
如果你先 ret[i] = count[i]; 然后 ret.pop_back(); 多次循环后,vector 为空,此时再访问就会报错空指针 Null Pointer 错误

时间 O(n * !n),空间 O(n)

cpp 复制代码
class Solution {
private:

    vector<vector<int>> ans;
    vector<int> ret; // 临时答案
    bool vis[7]; // 标记数组--需要回溯

    void dfs(vector<int>& nums, int count) {
        int n = nums.size();

        // 递归出口
        if (count == n) {
            ans.push_back(ret);
            return;
        }
        
        // 遍历每个位置
        for (int i = 0; i < n; ++i) {
            if (vis[i] == 0) {
                ret.push_back(nums[i]); // 加入答案数组
                vis[i] = 1; // 标记
                dfs(nums, count + 1); // 递归

                vis[i] = 0; // 取消标记
                ret.pop_back(); // 取消标记
            }
        }
    }

public:

    vector<vector<int>> permute(vector<int>& nums) {\
        dfs(nums, 0);
        return ans;
    }

};

🚩子集

78. 子集 - 力扣(LeetCode)

指数型枚举哦~

AC DFS

只有 选 / 不选 两种

时间 O(n * 2^n),空间 O(n)

cpp 复制代码
class Solution {
private:
    vector<vector<int>> ans;
    vector<int> ret; // 临时答案
public:
    void dfs(vector<int>& nums, int count) {
        int n = nums.size();
        // 递归出口
        if (count == n) {
            ans.push_back(ret);
            return;
        }
        // 选 OR 不选

        // 选
        ret.push_back(nums[count]); // 类似标记
        dfs(nums, count + 1); // 递归
        ret.pop_back(); // 类似取消标记

        // 不选
        dfs(nums, count + 1);
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums, 0);
        return ans;
    }
};

🎂电话号码的字母组合

17. 电话号码的字母组合 - 力扣(LeetCode)

AC DFS

空数组是 {},而不是 [],编译器看不懂这种 lambda 表达式
本题不要标记,因为,比如 "222",是可以取 "aaa" 的

3 个字母的数字输入 m 个,4 个字母的输入 n 个

时间 O(3^m * 4^n) -- 遍历每一种字母组合

cpp 复制代码
/*
1)  n 个数字, 每个数字取 1 个字母, 共取出 n 个字母
2) 取出的 n 个字母,按顺序组合起来 -- O(1)
*/
class Solution {
private:

    string ret; // 临时答案
    vector<string> ans;
    string num_alpha[10] = {"", "", "abc", "def", "ghi", "jkl", 
                                   "mno", "pqrs", "tuv", "wxyz"};
    
    // 已选 count 个数字
    void dfs(string digits, int count) {
        int n = digits.size();
        if (count == n) {
            ans.push_back(ret);
            return;
        }
        int num = digits[count] - '0'; // 当前数字
        string now = num_alpha[num]; // 当前字符串
        // 取一个字母
        for (int i = 0; i < now.size(); ++i) {
            ret.push_back(now[i]); // 插入字母

            dfs(digits, count + 1); // 递归

            ret.pop_back(); // 回溯时,便于填充其他字母
        }
    }

public:
    vector<string> letterCombinations(string digits) {
        // 特判空字符串, 返回空数组, 而不是包含空字符串的数组 [""]
        if (digits == "")
            return {};
        dfs(digits, 0);
        return ans;
    }
};

🌼组合总和

39. 组合总和 - 力扣(LeetCode)

AC DFS

1)指数型枚举的前提下,一个数字可以 "无限制重复" 被选取
2)还要考虑到,这题是 组合 问题,相同组合不同排列 ,视为++同一种结果++
3)分两种情况讨论,选 / 不选,注意参数的不同

cpp 复制代码
class Solution {
private:
    vector<vector<int>> ans;
    vector<int> ret; // 临时答案

    // num - candidates[i], num == 0 得到一个结果
    // 剩余 num, 第 start 个数字
    void dfs(vector<int>& candidates, int num, int start) {
        int n = candidates.size();
        // 递归出口
        if (start >= n) return;

        // 一种结果
        if (num == 0) {
            ans.push_back(ret);
            return;
        }

        // 选(当前数字)

        // 不超过 target
        if (num - candidates[start] >= 0) {
            ret.push_back(candidates[start]);
            dfs(candidates, num - candidates[start], start); // 选当前数字
            ret.pop_back(); // 恢复现场
        }

        // 不选(当前数字)
        dfs(candidates, num, start + 1); // 递归下一个
    }
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
    dfs(candidates, target, 0); // 剩余 target, 第 0 个数字开始
    return ans;
    }
};
相关推荐
sweetheart7-71 天前
LeetCode17. 电话号码的字母组合(2024秋季每日一题 59)
算法·深度优先·力扣·dfs
闻缺陷则喜何志丹4 天前
【C++ 曼哈顿距离 数学】1131. 绝对值表达式的最大值|2059
c++·数学·算法·力扣·最大值·哈曼顿距离·绝对值
银氨溶液5 天前
力扣——113. 路径总和
数据结构·算法·leetcode·职场和发展·dfs·回溯
王老师青少年编程6 天前
CSP/信奥赛C++刷题训练:经典深搜例题(1):洛谷1605 :迷宫
c++·算法·dfs·深搜·csp·信奥赛
丶Darling.6 天前
代码随想录 | Day36 | 动态规划 :整数拆分&不同的二叉搜索树
c++·笔记·学习·算法·动态规划·dfs·记忆化搜索
闻缺陷则喜何志丹6 天前
【C++动态规划 分组背包】1981. 最小化目标值与所选元素的差|2009
c++·算法·动态规划·力扣·最小化··分组背包
sweetheart7-77 天前
LeetCode994. 腐烂的橘子(2024秋季每日一题 54)
力扣·图论·bfs·宽度优先
伪编辑科学家7 天前
[每日一练]分组后元素最多的组别(all函数的全局比对)
sql·mysql·leetcode·数据分析·力扣·全局对比
闻缺陷则喜何志丹7 天前
【C++动态规划 多重背包】1774. 最接近目标价格的甜点成本|1701
c++·算法·动态规划·力扣·多重背包·成本·最接近
高雪峰9137 天前
C语言日记 2024年10月31日
c语言·力扣