DFS深度优先搜索与回溯算法

目录

递归遍历的三步骤:

DFS/回溯模板 

 练习

1.三角形路径和最大搜索

 (一)前序DFS(从上至下搜索,实际是暴力解法,测试超时)

(二)后序DFS(自底向上搜索,设置memory数组记录各节点子树的最大路径和,相同子树剪枝优化,AC)

(1)递归无返回值

(2)递归有返回值


         DFS是一种遍历/搜索树和图的算法,感觉和回溯算法类似,思想都是沿着树的深度进行(按照前序/中序/后序)递归搜索,直至搜索到某一路径的叶节点(或满足某终止条件),后沿深度进行回溯,搜索其余路径。访问完所有可能路径后,返回目标任务最优解或所有满足条件的路径。

        这实际就是一种暴力解法,时间复杂度高,为了提高算法效率,可分析题目,结合记忆法等对树进行剪枝优化

递归遍历的三步骤:

1.递归函数的参数、返回值(每层递归需要处理的数据)

2.递归终止条件(终止条件错误总会导致操纵系统的内存栈溢出错误)

3.单层递归逻辑(每层递归需要执行的操作)

DFS/回溯模板 

void dfs(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本节点所连接的其他节点) {
        处理节点;
        dfs(图,选择的节点); // 递归
        回溯,撤销处理结果
    }
}

 练习

1.三角形路径和最大搜索

 (一)前序DFS(从上至下搜索,实际是暴力解法,测试超时)

#include<iostream>
#include<vector>
using namespace std;
 
void output(vector<vector<int>>& input){
    for(int i=0; i<input.size(); i++){
        for(auto it=input[i].begin(); it!= input[i].end(); it++){
            cout<<*it<<" ";
        }
        cout<<endl;
    }
}
 
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
{
private:
    int maxSum;
    // 前序深度遍历
    void traversal(vector<vector<int>>& tree, int depth, int width, int sum){
        //
        if(depth >= tree.size()){
            if(sum > maxSum) maxSum = sum;
            return;
        }
        // mid
        sum += tree[depth][width];
        // left
        traversal(tree, depth+1, width, sum);
        // right
        traversal(tree, depth+1, width+1, sum);
    }
public:
    int getMaxPathSum(vector<vector<int>>& input_tree){
        maxSum = -1;
        traversal(input_tree, 0, 0, 0);
        return maxSum;
    }
};
 
int main()
{
    // input;
    int num;
    cin>>num;
    while(num--){
        vector<vector<int>> input_tree;
        int depth;
        cin>>depth;
        for(int i=1; i<=depth; i++){
            vector<int> tmp;
            int input;
            for(int j=0; j<i; j++){
                cin>>input;
                tmp.push_back(input);
            }
            input_tree.push_back(tmp);
        }
         
        // // debug_input
        // output(input_tree);
         
        solution mySolve;
        int res = mySolve.getMaxPathSum(input_tree);
        cout<<res<<endl;
    }
    return 0;
}

(二)后序DFS(自底向上搜索,设置memory数组记录各节点子树的最大路径和,相同子树剪枝优化,AC)

(1)递归无返回值

#include<iostream>
#include<vector>
using namespace std;
 
 
void debug_input(vector<vector<int>>& input){
    for(int i=0; i<input.size(); i++){
        for(auto it=input[i].begin(); it!=input[i].end(); it++){
            cout<<*it<<" ";
        }
        cout<<endl;
    }
}
 
class solution
{
private:
    vector<vector<int>> memory;// 记录每个子树maxSum
    // 从下至上遍历->后序->相同子树剪枝
    void traversal(vector<vector<int>>& input, int depth, int width){
        // 终止条件->遇叶节点
        if(depth == input.size()-1){
            memory[depth][width] = input[depth][width];
            return;
        }
        // 遇相同子树->剪枝
        if(memory[depth][width]) return;
         
        // 后序遍历
        // left
        traversal(input, depth+1, width);
        // right
        traversal(input, depth+1, width+1);
        // mid
        memory[depth][width] = input[depth][width] + max(memory[depth+1][width], memory[depth+1][width+1]);
    }
public:
    int getMaxPathSum(vector<vector<int>>& input){
        vector<int> vec(input.size(), 0);
        memory.resize(input.size(), vec);
        traversal(input, 0, 0);
        return memory[0][0];
    }
};
 
int main()
{
    int num;
    cin>>num;
    while(num--){
        vector<vector<int>> input;
        int depth;
        cin>>depth;
        for(int i=1; i<=depth; i++){
            vector<int> tmp;
            for(int j=0; j<i; j++){
                int in;
                cin>>in;
                tmp.push_back(in);
            }
            input.push_back(tmp);
        }
        // debug_input(input);
         
        solution my_solve;
        int res = my_solve.getMaxPathSum(input);
        cout<<res<<endl;
    }
    return 0;
}

(2)递归有返回值

#include<iostream>
#include<vector>
using namespace std;
 
 
void debug_input(vector<vector<int>>& input){
    for(int i=0; i<input.size(); i++){
        for(auto it=input[i].begin(); it!=input[i].end(); it++){
            cout<<*it<<" ";
        }
        cout<<endl;
    }
}
 
class solution
{
private:
    vector<vector<int>> memory;// 记录每个子树maxSum
    // 从下至上遍历->后序->相同子树剪枝
    int traversal(vector<vector<int>>& input, int depth, int width){
        // 终止条件->遇叶节点
        if(depth >= input.size()-1){
            return input[depth][width];
        }
        // 遇相同子树->剪枝
        if(memory[depth][width]) return memory[depth][width];
         
        // 后序遍历
        // left
        int left_sum = traversal(input, depth+1, width);
        // right
        int right_sum = traversal(input, depth+1, width+1);
        // mid
        memory[depth][width] = input[depth][width] + max(left_sum, right_sum);
        return memory[depth][width];
    }
public:
    int getMaxPathSum(vector<vector<int>>& input){
        vector<int> vec(input.size(), 0);
        memory.resize(input.size(), vec);
        int res = traversal(input, 0, 0);
        return res;
    }
};
 
int main()
{
    int num;
    cin>>num;
    while(num--){
        vector<vector<int>> input;
        int depth;
        cin>>depth;
        for(int i=1; i<=depth; i++){
            vector<int> tmp;
            for(int j=0; j<i; j++){
                int in;
                cin>>in;
                tmp.push_back(in);
            }
            input.push_back(tmp);
        }
        // debug_input(input);
         
        solution my_solve;
        int res = my_solve.getMaxPathSum(input);
        cout<<res<<endl;
    }
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

复制和粘贴文本时剥离格式的5种方法(MacWindows)

您可能每天复制和粘贴多次。虽然它是一个非常方便的功能&#xff0c;但最大的烦恼之一就是带来了特殊的格式。从网络上获取一些文本&#xff0c;您经常会发现粘贴到文档中时&#xff0c;它保持原始样式。 我们将展示如何使用一些简单的技巧在不格式化的情况下复制和粘贴。 1.…

ubuntu20安装mongodb

方法一&#xff1a;直接安装(命令是直接从mongo官网Install MongoDB Community Edition on Ubuntu — MongoDB Manual复制的&#xff09; cat /etc/lsb-release sudo apt-get install -y gnupg curl curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \sudo gp…

Qt 字符串类应用与常用基本数据类型

目录 操作字符串 查询字符串 Qt 常见数据类型 操作字符串 创建一个控制台项目 &#xff08;1&#xff09;QString提供一个二元的 “” 操作符&#xff0c;主要用于组合两个字符串。QString str1 "Hello World 传递给QString一个 const char* 类型的ASCII字符串 “He…

django线上教育学习平台大数据分析系统python

随着互联网技术不断地发展&#xff0c;网络与大数据成为了人们生活的一部分&#xff0c;而线上教育平台大数据分析作为网上应用的一个全新的体现&#xff0c;由于其特有的便捷性&#xff0c;已经被人们所接受。目前主流的线上教育平台大数据分析服务不仅不明确并且管理盈利较低…

Tkinter教程22:DataFrame数据加入到treeview树视图(含横纵滚动条+正反排序)

------------★Tkinter系列教程★------------ Tkinter教程21&#xff1a;Listbox列表框OptionMenu选项菜单Combobox下拉列表框控件的使用绑定事件 Tkinter教程20&#xff1a;treeview树视图组件&#xff0c;表格数据的插入与表头排序 Python教程57&#xff1a;tkinter中如何…

SpringCloud-Eureka原理分析

Eureka是Netflix开源的一款用于实现服务注册与发现的工具。在微服务架构中&#xff0c;服务的动态注册和发现是必不可少的组成部分&#xff0c;而Eureka正是为了解决这一问题而诞生的。 一、为何需要Eureka 在微服务架构中&#xff0c;服务之间的协同合作和高效通信是至关重要…

[计算机提升] 备份系统:系统映像

6.3 备份系统&#xff1a;系统映像 备份系统和还原系统是一套互补的操作。 操作系统的备份就是将操作系统当前的所有数据复制到硬盘的一个空闲区域&#xff0c;以防止系统崩溃或数据丢失。还原操作则是将先前备份的数据恢复到操作系统中&#xff0c;使系统回到之前的样子&…

17:定时器编程实战

1、实验目的 (1)使用定时器来完成LED闪烁 (2)原来实现闪烁时中间的延迟是用delay函数实现的&#xff0c;在delay的过程中CPU要一直耗在这里不能去做别的事情。这是之前的缺点 (3)本节用定时器来定一个时间&#xff08;譬如0.3s&#xff09;&#xff0c;在这个定时器定时时间内…

Python解决SSL不可用问题

参考&#xff1a;https://blog.csdn.net/weixin_44894162/article/details/126342591 一、问题描述&#xff1a; 报错概述&#xff1a; WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. ## 警告:pip配…

Prime(VulnHub)

Prime 文章目录 Prime1、nmap2、web渗透随便看看首页隐写查看目录爆破gobusterferoxbusterdirsearchdirb whatwebsearchsploit WordPress 5.2.2/dev/secret.txtFuzz_For_Webwfuzzimage.phpindex.php location.txtsecrettier360文件包含漏洞包含出password.txt尝试ssh登入尝试登…

VTK 体渲染设置帧率

当我们的mapper采样距离设置较低或者硬件性能不太好时&#xff0c;体渲染交互会有卡顿现象。为了提高交互时的流畅性&#xff0c;可以设置交互器的SetDesiredUpdateRate来降低采样率进而避免卡顿现象。 vtkNew<vtkRenderWindowInteractor> iren; iren->SetDesiredUpd…

Python速成篇(基础语法)上

引言 都是我手欠非要报什么python的计算机二级&#xff0c;现在好了假期不但要冲C艹&#xff0c;还要学个python&#xff0c;用了几天的时间速成了一下python的基础语法&#xff0c;其实在学会C的基础上&#xff0c;py学起来是非常的快啊。这篇博客呢&#xff0c;建议有一定语…

图论与图数据应用综述:从基础概念到知识图谱与图智能

目录 前言1 图论基础概念1.1 节点度1.2 度分布1.3 邻接矩阵 2 探索图的高级概念2.1 最短路径的关键性2.2 图的直径与平均路径的意义2.3 循环与路径类型的多样性 3 深入探讨图的广泛应用领域3.1 知识图谱的知识管理3.2 图智能在复杂决策中的应用3.3 图数据挖掘与分析的多领域应用…

C++三剑客之std::any(一) : 使用

相关系列文章 C三剑客之std::any(一) : 使用 C之std::tuple(一) : 使用精讲(全) C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)&#xff1a;深入剖析​​​​​​​ 目录 1.概述 2.构建方式 2.1.构造函数 2.2.std::make_any 2.3.operator分配新值 3.访问值…

我的docker随笔43:问答平台answer部署

本文介绍开源问答社区平台Answer的容器化部署。 起因 笔者一直想搭建一个类似stack overflower这样的平台&#xff0c;自使用了Typora&#xff0c;就正式全面用MarkdownTyporagit来积累自己的个人知识库&#xff0c;但没有做到web化&#xff0c;现在也还在探索更好的方法。 无…

Spring Boot3整合Redis

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 1.导依赖 2.配置连接信息以及连接池参数 3.配置序列化方式 4.编写测试 前置条件 已经初始化好一个spr…

RisingWave 中文用户文档上线,阅读更高效!

为满足广大中文社区用户、开发者及流处理技术爱好者的需求&#xff0c;RisingWave 用户文档中文社区版今天上线了&#xff01; 中文版文档的推出&#xff0c;旨在为广大用户提供更便捷、高效的阅读体验&#xff0c;帮助大家深入理解并有效使用 RisingWave&#xff0c;发挥其更…

零基础学Python之整合MySQL

Python 标准数据库接口为 Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。 不同的数据库你需要下载不同的DB API模块&#xff0c;例如你需要访问Oracle数据库和Mysql数据&#xff0c;你需要下载Oracle和MySQL数据库模块。 DB-API 是一个规范. 它…

2023年12月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 一个非零的二进制正整数,在其末尾添加两个“0”,则该新数将是原数的?( ) A:10倍 B:2倍 C:4倍 D:8倍 答案:C 二进制进位规则是逢二进一,因此末尾添加一个0,是扩大2倍,添加两个0…

【排序】希尔排序

算法图解 算法基本步骤 首先&#xff0c;希尔排序是基于插入排序的一个时间复杂度为O(N*logN)的一个很牛的排序。 大家应该能注意到&#xff0c;图解中每一趟排序的时候有的数背景颜色是一样的&#xff0c;像这样背景颜色相同的数为一组&#xff0c;我们一共可以分gap组。 那…