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;}// midsum += tree[depth][width];// lefttraversal(tree, depth+1, width, sum);// righttraversal(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;// 后序遍历// lefttraversal(input, depth+1, width);// righttraversal(input, depth+1, width+1);// midmemory[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];// 后序遍历// leftint left_sum = traversal(input, depth+1, width);// rightint right_sum = traversal(input, depth+1, width+1);// midmemory[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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

222. 完全二叉树的节点个数 - 力扣(LeetCode)

题目描述 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干…

axios get 请求 url 转码 空格转成+,导致请求失败(前端解决)

问题 GET 请求参数&#xff1a; URL-encoded 后&#xff1a; 浏览器将空格转成了&#xff0c;导致服务报错&#xff0c;返回 400。 解决 在请求拦截器中&#xff0c;对 params 进行处理。 axios.interceptors.request.use((config) > {let url config.url;if (config…

SpringCloud-Eureka原理分析

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

【学网攻】 第(23)节 -- PPP协议

系列文章目录 目录 系列文章目录 文章目录 前言 一、PPP协议是什么&#xff1f; 二、实验 1.引入 实验目的 实验背景你是某公司的网络管理员&#xff0c;现在需要与另一个公司进行通信,需要你配置PPP协议保证双方发送的人是真正的而非黑客 技术原理 实验步骤新建Pack…

vue 引入 百度地图API 和 路书

公司项目中&#xff0c;偶尔都会涉及到地图的使用&#xff0c;这里以百度地图为例&#xff0c;我们梳理一下引用流程及注意点 账号和获取密钥 百度地图示例 百度地图 类参考 1、账号和获取密钥 // api.map.baidu.com/api?typewebgl&v3.0&ak您的密钥<script type…

Git 消除对某个文件的追踪

参考&#xff1a; &#xff08;尚未验证他的该方法&#xff09; https://www.golinuxcloud.com/git-remove-file-from-tracking/https://www.golinuxcloud.com/git-remove-file-from-tracking/

parse库,一个优雅的python库

前言 在Python中&#xff0c;format方法和f-strings是两种常用的字符串插值方法。 name "Haige" age "18" print(f"{name} is {age} years old.")# Haige is 18 years old.而如果是要从字符串中提取期望的值呢&#xff1f;相信很多人的第一或…

假期作业5

TCP和UDP区别 TCP ----稳定 1、提供面向连接的&#xff0c;可靠的数据传输服务&#xff1b; 2、传输过程中&#xff0c;数据无误、数据无丢失、数据无失序、数据无重复&#xff1b; 3、数据传输效率低&#xff0c;耗费资源多&#xff1b; 4、数据收发是不同步的&#xff1b; U…

【Flink入门修炼】1-3 Flink WordCount 入门实现

本篇文章将带大家运行 Flink 最简单的程序 WordCount。先实践后理论&#xff0c;对其基本输入输出、编程代码有初步了解&#xff0c;后续篇章再对 Flink 的各种概念和架构进行介绍。 下面将从创建项目开始&#xff0c;介绍如何创建出一个 Flink 项目&#xff1b;然后从 DataStr…

flutter开发实战-ijkplayer视频播放器功能

flutter开发实战-ijkplayer视频播放器功能 使用better_player播放器进行播放视频时候&#xff0c;在Android上会出现解码失败的问题&#xff0c;better_player使用的是video_player&#xff0c;video_player很多视频无法解码。最终采用ijkplayer播放器插件&#xff0c;在flutt…

[机器学习]K-means——聚类算法

一.K-means算法概念 二.代码实现 # 0. 引入依赖 import numpy as np import matplotlib.pyplot as plt # 画图依赖 from sklearn.datasets import make_blobs # 从sklearn中直接生成聚类数据# 1. 数据加载 # 生成&#xff08;n_samples&#xff1a;样本点&#xff0c;centers&…

06-OpenFeign-使用HtppClient连接池

默认下OpenFeign使用URLConnection 请求连接&#xff0c;每次都需要创建、销毁连接 1、添加ApacheHttpClient依赖 <!-- 使用Apache HttpClient替换Feign原生httpclient--><dependency><groupId>org.apache.httpcomponents</groupId><artifact…