dfs专题7—— 全排列

🔥近津薪荼: [个人主页] 🎬个人专栏: 《近津薪荼的算法日迹》 《Linux操作系统及网络基础知识分享》 《c++基础知识详解》 《c语言基础知识详解》 ✨不要物化,矮化,弱化,钝化自己,保持锋芒,不要停止学习 这个世界上只有两个人真正在注意着你 八岁的你,和八十岁的你, 他们此刻正在注视着你, 一个希望你 勇敢开始 ,一个希望你 不留遗憾


1.上期参考代码

全局变量

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
vector<string> ret; 
string path;       
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        if(root==nullptr) return ret;
        dfs(root);
        return ret;
    }

    void dfs(TreeNode* root) {
        if(root==nullptr) return ;

        // 记录当前节点值的长度,后边回溯会用
        int val_len = to_string(root->val).size();
        path += to_string(root->val);
        if(root->left==nullptr && root->right==nullptr) {
            ret.push_back(path);
        } else {
            // 非叶子节点,才拼接"->"
            if(root->left) {
                path += "->";
                dfs(root->left);
                // 回溯:删除拼接的"->"(2个字符)
                path.pop_back();
                path.pop_back();
            }
            if(root->right) {
                path += "->";
                dfs(root->right);
                path.pop_back();
                path.pop_back();
            }
        }

        // 回溯:删除当前节点的值(按长度删)
        for(int i = 0; i < val_len; i++) {
            path.pop_back();
        }
    }
};

传值传参

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
vector<string> ret;
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        
        string path;
        if(root==nullptr) return ret;
        dfs(root,path);
        return ret;
    }
        void dfs(TreeNode* root,string path)
        {
            if(root==nullptr)return ;
///////////////////////////////////////////////////////////////////出口
            path += to_string(root->val);
            if(root->left==nullptr&&root->right==nullptr)
            {
                ret.push_back(path);
            }
            path +="->";
            dfs(root->left,path);
            dfs(root->right,path);
/////////////////////////////////////////////////////////////////每一层子问题要做的事
        }
};

2.本期知识点导图

3.本期要讲解的题目是

全排列

要点:

  • 就是高中学的排列

4.解题

4.1 暴力解法:枚举

嵌套循环,一 一枚举,有几个数就套几层循环,第一层循环做第一个数,以此类推,时间复杂度爆大

4.2优解

我们上过初高中吧,那肯定也画过树状图来解决简单的排列组合吧

我们来画一个:

在我们的算法思想中,上边画的树状图是一个决策树

什么是决策树?

  • 决策树就是像问问题一样层层分叉、根据特征一步步筛选,最终得到分类或预测结果的树形判断模型。

听上去高大上,说白了就是画树状图分析问题

我们后续学习难一点的dfs,都要开始画决策图啦

我们的回溯和剪枝思想离不开决策图 ,画图能帮助我们快速决策什么地方剪枝,回溯应该怎么操作

比如这题:

  • 全排列,没有重复的元素(所以对使用过的元素,我们应该加上标记),我画红叉的地方就是该剪枝的地方。
  • 回溯时的操作应该是将使用标记改成未使用,将放入数组的元素删去(结合代码逻辑理解)

为什么一定要有回溯操作?

以后做dfs的题,我们可以先画决策图,不是递归图,是决策图,看图写代码会顺畅很多。

代码逻辑

  • 先画图
    通过分析我们发现需要做三个核心操作
  1. 用一维数组path记录元素形成排列
  2. 用二维数组ret记录排列,作为返回值
  3. 用一个bool类型的数组记录元素是否被使用过
  • 重复子问题:求一组元素的排列(每次求得排列不得重复)

    看看上边用到的数组,如果全部设置成函数参数,那会变得很麻烦。

    那就意味着我们得使用全局变量,使用全局变量的话,回溯操作不可避免的~~

  • 子问题干什么

  1. 将未使用过的元素放入path(剪枝
  2. 将元素标记成已使用
  3. 排列剩下的元素
  4. 回溯:将刚才的元素置为未使用,并移出path
  • 出口:当path放满nums.size( )个元素时,将path放如ret,返回

提示:数组递归,经常使用for循环来建立框架

5.下期要讲解的题目是:

子集

6.嗟食

如果小编写的内容对佬有帮助,还请大佬点点三连加关注哦
佬的支持就是我前进的最大动力 ~

期待与佬的再次相遇~

相关推荐
沐苏瑶16 小时前
Java 搜索型数据结构全解:二叉搜索树、Map/Set 体系与哈希表
java·数据结构·算法
لا معنى له16 小时前
WAM与AC-WM:具身智能时代的世界动作模型与动作条件世界模型
人工智能·笔记·学习
ZoeJoy817 小时前
算法筑基(二):搜索算法——从线性查找到图搜索,精准定位数据
算法·哈希算法·图搜索算法
Alicx.17 小时前
dfs由易到难
算法·蓝桥杯·宽度优先
桦017 小时前
【C++复习】:继承
开发语言·c++
_日拱一卒17 小时前
LeetCode:找到字符串中的所有字母异位词
算法·leetcode
鱼难终17 小时前
类和对象(下)
c++
云泽80818 小时前
深入 AVL 树:原理剖析、旋转算法与性能评估
数据结构·c++·算法
薛先生_09918 小时前
js学习语法第一天
开发语言·javascript·学习
Wilber的技术分享18 小时前
【LeetCode高频手撕题 2】面试中常见的手撕算法题(小红书)
笔记·算法·leetcode·面试