C++ DFS

news2024/11/25 2:53:30

 子集

78. 子集

 法一:思路对每个元素进行选与不选的  选择,这样正好到最后一层 就是2的size()次方个,叶子就是节点,通过pos来控制深度

 

法二:通过for循环实现,且下一个栈帧的i是上一个栈帧当前元素的下一个位置 ,能起到vis的作用刚开始写的时候把这个->dfs(nums, i + 1); 写成了dfs(nums, pos + 1);

 

解释为什么dfs(nums, pos + 1);是错的且当样例为[1,2,3]时有16个结果 

其实就是逻辑上不对,每一个for循环进到下一个栈帧的区间都是一样的,这就是问题所在;

总结:在for里i=pos上,有一点点语法的混淆,加上脑子不清醒,逻辑不清晰,梳理好了在写,不然还得重新检查

法一:

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if(pos == nums.size()) 
        {
            ret.push_back(path); 
            return;
        }
        path.push_back(nums[pos]);
        dfs(nums, pos + 1);

        path.pop_back();
        dfs(nums,pos + 1);
    }
};

法二: 

class Solution {
public:
    vector<int> path;
    vector<vector<int>> ret;
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        ret.push_back(path);
        for(int i = pos; i < nums.size(); i++)
        {
            path.push_back(nums[i]);
            dfs(nums, i + 1);
            path.pop_back();
            
        }
    }
};

全排列 

 46. 全排列

 通过pos来控制栈帧深度,pos+1来增加深度,pos也是用来取值的

在代码上表现逻辑:当需要dfs往下走的时候,需要对已经当前元素改bool值,来保证到下一层不被使用;当dfs回来之后自然的要把当前元素弹出path(其实每个栈的深度,就是这个元素在path里的位置)我们只需要弹出它,让他去后面的其他位置,同时需要解锁bool值

题外话:保持其他代码不变,删掉弹出语句,最大长度是多少?

答:15个,第一个栈帧可以发送3个值,同时需要三个栈帧(注意:在此时深度仍然是2),这三个栈帧每个可以向下个栈帧发送2个值,会有6个栈帧;这6个栈帧每个可以发送一个值,那就是2+3*2+6=15,一共会创建16个栈帧(因为到进不去for那个栈帧才结束),最大深度为4

 

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    vector<bool> vis;
    //bool[6];
    vector<vector<int>> permute(vector<int>& nums) {
        vis.resize(nums.size());
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if(pos == nums.size())
        {
            ret.push_back(path);
            return;
        }
        for(int i = 0; i < nums.size(); i++)
        {
            if(vis[i] == true) continue;
            path.push_back(nums[i]);
            vis[i] = true;
            
            dfs(nums, pos + 1);
            path.pop_back();
            vis[i] = false;
        }
    }
};

 找出所有子集的异或总和再求和

1863. 找出所有子集的异或总和再求和

 

class Solution {
public:
    int ret = 0;
    int subsetXORSum(vector<int>& nums) {
        dfs(nums, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int sum)
    {
        ret += sum;
        for(int i = pos; i < nums.size(); i++)
        {
            sum = sum ^ nums[i];
            dfs(nums, i + 1, sum);
            sum ^= nums[i];
        }
    }
};

全排列 II 

 47. 全排列 II

1. 去重想到的就是set,set里放vector<int>

2. 剪枝

class Solution {
public:
    set<vector<int>> set;
    vector<bool> vis;
    vector<int> path;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vis.resize(nums.size());
        dfs(nums, 0);
        vector<vector<int>> ret(set.begin(), set.end());
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if(path.size() == nums.size())
        {
            set.insert(path);
        }
        for(int i = 0; i < nums.size(); i++)
        {
            if(vis[i]) continue;
            path.push_back(nums[i]);
            vis[i] = true;
            dfs(nums, pos + 1);
            vis[i] = false;
            path.pop_back();
        }
    }
};
class Solution {
public:
    vector<bool> vis;
    vector<int> path;
    vector<vector<int>> ret;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vis.resize(nums.size());
        sort(nums.begin(), nums.end());
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if(pos == nums.size())
        {
            ret.push_back(path);
            return;
        }
        for(int i = 0; i < nums.size(); i++)
        {
            if(vis[i] == true || 
                i != 0 && nums[i] == nums[i - 1] && vis[i - 1] == false) continue;
            path.push_back(nums[i]);
            vis[i] = true;
            dfs(nums, pos + 1);
            path.pop_back();
            vis[i] = false;
        }
    }
};

 电话号码的字母组合

 17. 电话号码的字母组合

 代码问题:arr[digits[pos] - '0'];忘记是字符了

逻辑问题:digiis可能是空串,空串进入dfs就会被压入 "" 空字符串

class Solution {
public:
    vector<string> arr{ "","","abc","def" ,"ghi","jkl","mno","pqrs","tuv","wxyz"};
    vector<string> ret;
    string path;
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0) return ret;
        dfs(digits, 0);
        return ret;
    }
    void dfs(string digits, int pos)
    {
        if (pos == digits.size())
        {
            ret.push_back(path);
            return;
        }
        string tmp = arr[digits[pos] - '0'];
        for (auto e : tmp)
        {
            path.push_back(e);
            dfs(digits, pos + 1);
            path.pop_back();
        }
    }
};

 组合

77. 组合

 

class Solution {
public:
    vector<int> path;
    vector<bool> vis;
    vector<vector<int>> ret;
    int _k;
    vector<vector<int>> combine(int n, int k) {
        _k = k;
        vector<int> arr(n);
        for (int i = 0; i < n; i++)
            arr[i] = i + 1;
        dfs(arr, 0);
        return ret;
    }
    void dfs(vector<int>& arr, int pos)
    {
        if (path.size() == _k)
        {
            ret.push_back(path);
            return;
        }
        for (int i = pos; i < arr.size(); i++)
        {
            path.push_back(arr[i]);
            dfs(arr, i + 1);
            path.pop_back();
        }
    }
};
class Solution {
public:
    vector<int> path;
    vector<vector<int>> ret;
    int _k, _n;
    vector<vector<int>> combine(int n, int k) {
        _k = k;
        _n = n;
        dfs(0);
        return ret;
    }
    void dfs(int pos)
    {
        if (path.size() == _k)
        {
            ret.push_back(path);
            return;
        }
        for (int i = pos; i < _n; i++)
        {
            path.push_back(i + 1);
            dfs(i + 1);
            path.pop_back();
        }
    }
};

 目标和

 494. 目标和

 

 发现局部sum不需要sum += nums[pos];这样的加回去的操作,因为每一个栈帧里的sum都是不一样的,而全局sum会一直改变,一个栈帧里的操作不能影响同层栈帧

 全局sum

class Solution {
public:
    int sum = 0, ret = 0,_target;
    int findTargetSumWays(vector<int>& nums, int target) {
        _target = target;
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if (pos == nums.size())
        {
            if (_target == sum)
                ret++;
            return;
        }
        sum += nums[pos];
        dfs(nums, pos + 1);
        sum -= nums[pos];

        sum -= nums[pos];
        dfs(nums, pos + 1);
        sum += nums[pos];
    }
};

局部sum 

class Solution {
public:
    int ret = 0,_target;
    int findTargetSumWays(vector<int>& nums, int target) {
        _target = target;
        dfs(nums, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int sum)
    {
        if (pos == nums.size())
        {
            if (_target == sum)
                ret++;
            return;
        }
        sum += nums[pos];
        dfs(nums, pos + 1, sum);
        sum -= nums[pos];

        sum -= nums[pos];
        dfs(nums, pos + 1, sum);
    }
};

 组合总和

 39. 组合总和

 参开代码

class Solution {
public:
    vector<int> path;
    int _target;
    vector<vector<int>> ret;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        _target = target;
        dfs(candidates, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int sum)
    {
        if(sum == _target)
        {
            ret.push_back(path);
            return;
        }
        if(sum > _target || pos == nums.size()) return;
        for(int i = 0; i * nums[pos] + sum <= _target; i++)
        {
            if(i) path.push_back(nums[pos]);
            dfs(nums, pos + 1, i * nums[pos] + sum);
            // while(i--)
            //     path.pop_back();    //不对必须是整个for结束,不然i走不下去了
        }
        for(int i = 1; i * nums[pos] + sum <= _target; i++) path.pop_back();
    }
};

 超时:

class Solution {
public:
    //vector<vector<int>> ret;
    int _target, sum = 0;
    vector<int> path;
    set<vector<int>> set;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> nums;
        for (auto e : candidates)
        {
            int n = target / e;
            for (int i = 0; i < n; i++)
                nums.push_back(e);
        }
        _target = target;
        dfs(nums, 0);
        vector<vector<int>> ret(set.begin(), set.end());
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if(sum == _target)
            set.insert(path);
        if (pos == nums.size()) return;

        for (int i = pos; i < nums.size(); i++)
        {
            path.push_back(nums[i]);
            sum += nums[i];
            dfs(nums, i + 1);

            sum -= nums[i];
            path.pop_back();
        }

    }
};

 括号生成

22. 括号生成

 条件约束递归

class Solution {
public:
    string path;
    vector<string> ret;
    int _n, left = 0, right = 0;
    vector<string> generateParenthesis(int n) {
        _n = n;
        dfs();
        return ret;
    }
    void dfs()
    {
        if(right == _n) 
        {
            ret.push_back(path);
            return;
        }
         if (left < _n)
        {
            path.push_back('(');
            left++, dfs();
            path.pop_back(); left--;
        }

        if (right < left)
        {
            path.push_back(')');
            right++, dfs();
            path.pop_back(); right--;
        }
    }

};

判断是不是平衡二叉树 

判断是不是平衡二叉树_牛客题霸_牛客网

dfs的返回值 :-1为false 非0为高度差,这个想法很6★★★★ 

left和right是不用+1的,因为这个1是root这个位置

class Solution {
public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
        return dfs(pRoot) != -1;
    }
   int dfs(TreeNode* root)
   {
       if (root == nullptr) return 0;
       int left = dfs(root->left);
       if (left == -1) return -1;
       int right = dfs(root->right);
       if (right == -1) return -1;

       return abs(left - right) <= 1 ? max(left, right) + 1: -1;
   }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1803616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣每日一题85:最大矩形

题目 困难 相关标签 相关企业 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 示例 1&#xff1a; 输入&#xff1a;matrix [["1","0","1","0",&q…

C++STL初阶(3):string模拟实现的完善

1.流提取>>的优化&#xff08;利用缓存区的思想&#xff09; istream& operator>>(istream& is,string& str) {str.clear();char c;c is.get();while (c ! \0 && c ! \n) {str c;c is.get();}return is; } 在上文的对string的实践中&#…

高考作文:时光之河,逐梦前行

时光之河&#xff0c;奔流不息&#xff0c;如同我们的人生旅途&#xff0c;充满了未知与挑战。站在2024年的高考门槛前&#xff0c;我们回望过去&#xff0c;展望未来&#xff0c;心中充满了期待与憧憬。 首先&#xff0c;让我们回顾一下这条时光之河中的点滴。过去的岁月里&am…

分享一个用python写的本地WIFI密码查看器

本章教程&#xff0c;主要分享一个本地wifi密码查看器&#xff0c;用python实现的&#xff0c;感兴趣的可以试一试。 具体代码 import subprocess # 导入 subprocess 模块&#xff0c;用于执行系统命令 import tkinter as tk # 导入 tkinter 模块&#xff0c;用于创建图形用…

vb开源项目推荐:PhotoDemon9.0一键批量去除图片水印

PhotoDemon 9.0作为一款开源免费的照片编辑器&#xff0c;提供了丰富的图片编辑和处理功能&#xff0c;可以通过PhotoDemon的批处理功能结合一些编辑技巧&#xff0c;来实现批量去除图片水印的目的。 以下是一个可能的步骤指南&#xff0c;用于在PhotoDemon 9.0中通过批处理间…

利用keepalived对zabbix-server做高可用,部署安装keepalived

有2台机器&#xff0c;每台都有1个zabbix-server&#xff0c;然后再每台上再装一个keepalived https://www.keepalived.org/download.html 1&#xff0c;创建安装路径 mkdir /usr/share/keepalived/2&#xff0c;在这个安装路径下面下载keepalived的软件包 我选的版本是1.3…

据报道,FTC 和 DOJ 对微软、OpenAI 和 Nvidia 展开反垄断调查

据《纽约时报》报道&#xff0c;联邦贸易委员会 (FTC) 和司法部 (DOJ) 同意分担调查微软、OpenAI 和 Nvidia 潜在反垄断违规行为的职责。 美国司法部将牵头对英伟达进行调查&#xff0c;而联邦贸易委员会将调查 OpenAI 与其最大投资者微软之间的交易。 喜好儿网 今年 1 月&a…

记录:linux桌面管理基础-X11协议(X window system)

1、认识X11 X11是X协议&#xff0c;版本号为11。X协议是专门被设计为linux桌面管理服务的&#xff0c;而linux桌面环境不像windows那样作为系统内核的一部分&#xff0c;作为一个普通程序运行在用户态上。该协议的设计初衷是为了linux的图形界面满足跨平台、跨网络、与具体硬件…

JVM面试基本问题整理

文章目录 1、说下对JVM内存模型的理解2、运行时常量池的位置3、常量池和运行时常量池的区别4、内存溢出和内存泄漏5、Java 对象大小计算6、GCROOT都有什么7、常用的JVM启动参数有哪些8、TLAB 1、说下对JVM内存模型的理解 1&#xff09;线程私有区域 程序计数器&#xff08;Pro…

ROS学习记录:栅格地图格式

一、机器人导航所使用的地图数据&#xff0c;就是ROS导航软件包里的map_server节点在话题 /map 中发布的消息数据&#xff0c;消息类型是nav_msgs消息包中的OccupancyGrid&#xff0c;它的中文意思的占据栅格&#xff0c;是一种正方形小格子组成的地图。 二、对障碍物进行俯视&…

单片机+TN901非接触式红外测温设计

摘要 温度测量技术应用十分广泛&#xff0c;而且在现代设备故障检测领域中也是一项非常重要的技术。但在某些应用领域中&#xff0c;要求测量温度用的传感器不能与被测物体相接触&#xff0c;这就需要一种非接触的测温方式来满足上述测温需求。本论文正是应上述实际需求而设计的…

搭建python虚拟环境,并在VSCode中使用

创建环境 python -m venv E:\python\flask\venv激活环境 运行下图所示的bat文件 退出环境 执行下面的语句 deactivateVSCode中配置&#xff1a; ①使用CTRLshiftp命令&#xff0c;使用CTRLshiftp命令&#xff0c;输入&#xff1a; Python: Select Interpreter②选择之前创建…

C++ 11 【线程库】【包装器】

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C修炼之路⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 目录 前言 一、thread类的简单介绍 get_id…

IO进程线程(七)代码替换函数、守护进程

文章目录 一、代码替换函数&#xff08;一&#xff09;system函数&#xff08;二&#xff09;exec函数族 二、守护进程&#xff08;一&#xff09;创建1. 脱离父进程影响2. 脱离原会话组和进程组的影响3.修改进程工作目录4. 修改进程创建文件的掩码5. 关闭从父进程继承的文件描…

轻松搞定阿里云域名DNS解析

本文将会讲解如何设置阿里云域名DNS解析。在进行解析设置之前&#xff0c;你需要提前准备好需要设置的云服务器IP地址、域名以及CNAME记录。 如果你还没有云服务器和域名&#xff0c;可以参考下面的方法注册一个。 申请域名&#xff1a;《Namesilo域名注册》注册云服务器&…

[Cloud Networking] Layer Protocol (continue)

文章目录 1. STP / RSTP / MSTP Protocol1.1 STP的作用1.2 STP 生成树算法的三个步骤1.3 STP缺点 2. ARP Protocol3. DHCP Protocol3.1 DHCP 三种分配方式3.2 DHCP 攻击 4. IPSEC / MACSEC 1. STP / RSTP / MSTP Protocol 1.1 STP的作用 消除二层环路&#xff1a;通过阻断冗余…

大模型,也在卷价格

“百模大战”已从算力战、规模战蔓延到了价格战。 5月15日&#xff0c;字节跳动宣布豆包主力模型&#xff08;小于等于32K&#xff09;在企业市场的定价只有0.0008元/千Tokens&#xff0c;0.8厘就能处理1500多个汉字&#xff0c;比行业便宜99.3%&#xff1b;5月21日&#xff0…

【乐吾乐3D可视化组态编辑器】用开关控制巡检车和路灯

一、运动设备开关控制 3D组态编辑器地址&#xff1a;3D可视化组态 - 乐吾乐Le5le 1.在场景中新建模拟运动设备及控制面板&#xff1a;启动/停止 2.单击巡检车设备新建模拟动画 3.设置模拟动画属性 4.单击启动面板&#xff0c;新建交互事件 5.设置交互触发类型&#xff0c;新建…

WinForms 应用(.NET 8.0)使用ReportViewerCore.WinForms显示打印RDLC报表

在要WinForms 应用&#xff08;.NET 8.0&#xff09;中&#xff0c;显示RDLC报表&#xff0c;就要使用ReportViewerCore.WinForms。原来的ReportViewer只能在.NET Framework框架下运行。 1.ReportViewerCore.WinForms 程序包说明 SQL Server Reporting Services ReportViewer…

使用CodeGen进行程序综合推理

Program Synthesis with CodeGen — ROCm Blogs (amd.com) CodeGen是基于标准Transformer的自回归语言模型家族&#xff0c;用于程序合成&#xff0c;正如作者所定义的&#xff0c;它是一种利用输入-输出示例或自然语言描述生成解决指定问题的计算机程序的方法。 我们将测试的…