[LeetCode]根据决策树设计代码解决dfs

目录

[46. 全排列 - 力扣(LeetCode)](#46. 全排列 - 力扣(LeetCode))

[78. 子集 - 力扣(LeetCode)](#78. 子集 - 力扣(LeetCode))


46. 全排列 - 力扣(LeetCode)

**决策树:**根据题意可以知道,全排列需要找到数组内元素不重复的所有排列方式,可以画出决策树如下图

设计代码:

  1. 全局变量: 1.用来保存所有排列结果的二维数组res 2.用来保存单个排列的数组path 3.不能有重复元素,每层选择需要避开已经选了的元素,需要一个布尔数组check确认该位置是否已经被选。
  2. **设计代码:**考虑单个节点,选判断该节点值是否被选,当未被选才进入该节点,进入该节点后path加上该节点值,后调用dfs进入下一层,从该层退出时,path要去掉该节点值。
  3. 细节:
    1. 递归出口:当到叶子节点时,单个排列path完成,该path加入res中,同时直接返回。
    2. 剪枝:当该节点位置布尔数组check[i]==true时,表示改为被选过了,不考虑该节点,就相当于剪枝了。
    3. 回溯:到达叶子节点时,添加上最后一个元素后,调用dfs到下一层会到递归出口,path加入res后直接返回后,回到上一层path去掉该节点值。

代码:

cpp 复制代码
class Solution {
    vector<vector<int>> res;
    vector<int> path;
    bool check[7];
public:
    void dfs(vector<int>& nums)
    {
        //递归出口
        if(nums.size()==path.size())
        {
            res.push_back(path);
            return;
        }
        for(int i=0;i<nums.size();i++)
        {
            //分析单个节点
            if(check[i]==false)
            {
                check[i]=true;
                path.push_back(nums[i]);
                dfs(nums);
                check[i]=false;
                path.pop_back();
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) 
    {
        dfs(nums);
        return res;
    }
};

78. 子集 - 力扣(LeetCode)

方案一

**决策树:**根据题意是找子集,遍历nums中的元素可选可不选,对于每种元素选或不选有两种选择,可画出nums.size()深度的决策树。

设计代码:

  1. 全局变量: 1.用来保存所有结果的二维数组res 2.用来保存单个子集的数组path
  2. 设计代码: 考虑单个节点,有选或不选两种选择(类似于二叉树,选相当于左子数,不选相当于右子树),要分别遍历,当选择时,将节点值加入path,调用dfs进入下一层,出该层时,path去掉节点值,不选择时,path不用加入该节点值,直接调用dfs进入下一层。到叶子节点时,path长度不一定会等于nums长度,需要加入参数pos记录层数。
  3. 细节:
    1. 递归出口:当递归层数达到nums.size()时,可将子集path加入res中,直接返回即可。
    2. 剪枝:由于每个元素都要判断是否选择,没有剪枝。
    3. 回溯:选叶子节点:叶子节点值加入path,进入dfs触发递归出口返回,path去掉该叶子节点,不选叶子节点,进入dfs,触发递归出口返回,该层结束到上一层。

代码:

cpp 复制代码
class Solution {
    vector<vector<int>> res;
    vector<int> path;

public:
    void dfs(vector<int> nums, int pos)
    {
        //出口
        if(pos==nums.size())
        {
            res.push_back(path);
            return;
        }

        //选
        path.push_back(nums[pos]);
        dfs(nums, pos+1);
        path.pop_back();

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

方案二

**决策树:**根据题意可在按遍历顺序选择一个节点后,在后面未选的元素中在遍历依次选择一个节点后进入下一层。

设计代码:

  1. 全局变量: 1.用来保存所有结果的二维数组res 2.用来保存单个子集的数组path
  2. **设计代码:**在方案一的基础上,考虑单个节点我们在每层只考虑该选节点的情况,加一个参数pos表示遍历到的nums数组下标,在未被遍历到的下标pos右边部分再遍历依次选择下一节点,由于只考虑要在未选的中选一个,所以每次进入一层都要将path加入res中。
  3. 细节:
    1. 递归出口:下标pos超过数组结尾就可以返回了,因为没有要处理的了,不加递归出口也可以。
    2. 剪枝:每次只在下标pos右边选,相当于剪枝了。
    3. 回溯:由于是考虑选哪个,不是选不选的问题,所以到最后叶子节点必是数组最后一个元素,处理完最后一个元素后,没有可选元素了,函数会直接返回。

代码:

cpp 复制代码
class Solution {
    vector<vector<int>> res;
    vector<int> path;
public:
    void dfs(vector<int> nums, int pos)
    {
        for(int i=pos;i<nums.size();i++)
        {
            path.push_back(nums[i]);
            res.push_back(path);
            dfs(nums, i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) 
    {
        vector<int> tmp;
        res.push_back(tmp);
        dfs(nums,0);
        return res;
    }
};
相关推荐
Blossom.11822 分钟前
量子计算在密码学中的应用与挑战:重塑信息安全的未来
人工智能·深度学习·物联网·算法·密码学·量子计算·量子安全
1白天的黑夜126 分钟前
贪心算法-860.柠檬水找零-力扣(LeetCode)
c++·算法·leetcode·贪心算法
搏博34 分钟前
专家系统的基本概念解析——基于《人工智能原理与方法》的深度拓展
人工智能·python·深度学习·算法·机器学习·概率论
yzx99101335 分钟前
决策树随机深林
人工智能·python·算法·决策树·机器学习
Y1nhl1 小时前
力扣hot100_子串_python版本
开发语言·python·算法·leetcode·职场和发展
uhakadotcom1 小时前
过来人给1-3 年技术新人的几点小小的建议,帮助你提升职场竞争力
算法·面试·架构
wuqingshun3141592 小时前
蓝桥杯 16. 密文搜索
c++·算法·职场和发展·蓝桥杯·深度优先
Brookty2 小时前
【数据结构】哈希表
数据结构·算法·哈希算法·散列表
Dovis(誓平步青云)3 小时前
【数据结构】·励志大厂版(复习+刷题):二叉树
c语言·数据结构·经验分享·笔记·学习·算法·学习方法
越城3 小时前
算法效率的钥匙:从大O看复杂度计算 —— C语言数据结构第一讲
c语言·开发语言·数据结构·算法