LeetCode--二叉树2--运用递归解决树的问题
LeetCode--二叉树2--运用递归解决树的问题
在前面的章节中,我们已经介绍了如何利用递归求解树的遍历。
递归是解决树的相关问题最有效和最常用的方法之一。
我们知道,树可以以递归的方式定义为一个节点(根节点),它包括一个值和一个指向其他节点指针的列表。 递归是树的特性之一。
因此,许多树问题可以通过递归的方式来解决。
对于每个递归层级,我们只能关注单个节点内的问题,并通过递归调用函数来解决其子节点问题。
通常,我们可以通过 “自顶向下” 或 “自底向上” 的递归来解决树问题。
自顶向下的解决方案
“自顶向下” 意味着在每个递归层级,我们将首先访问节点来计算一些值,并在递归调用函数时将这些值传递到子节点。
所以 “自顶向下的解决方案可以被认为是一种前序遍历。
具体来说,递归函数 top_down(root, params) 的原理是这样的:
1. return specific value for null node
2. update the answer if needed // anwer <-- params
3. left_ans = top_down(root.left, left_params) // left_params <-- root.val, params
4. right_ans = top_down(root.right, right_params) // right_params <-- root.val, params
5. return the answer if needed // answer <-- left_ans, right_ans
例如,思考这样一个问题:给定一个二叉树,请寻找它的最大深度.
我们知道根节点的深度是1。
对于每个节点,如果我们知道某节点的深度,那我们将知道它子节点的深度。
因此,在调用递归函数的时候,将节点的深度传递为一个参数,那么所有的节点都知道它们自身的深度。
而对于叶节点,我们可以通过更新深度从而获取最终答案。
这里是递归函数 maximum_depth(root, depth) 的伪代码:
1. return if root is null
2. if root is a leaf node:
3. answer = max(answer, depth); // update the answer if needed
4. maximum_depth(root.left, depth + 1) // call the function recursively for left child
5. maximum_depth(root.right, depth + 1) // call the function recursively for right child
C++ 代码
int answer; // don't forget to initialize answer before call maximum_depth
void maximum_depth(TreeNode* root, int depth) {
if (!root) {
return;
}
if (!root->left && !root->right) {
answer = max(answer, depth);
}
maximum_depth(root->left, depth + 1);
maximum_depth(root->right, depth + 1);
}
自底向上的解决方案
“自底向上” 是另一种递归方法。
在每个递归层次上,我们首先对所有子节点递归地调用函数,然后根据返回值和根节点本身的值得到答案。
这个过程可以看作是后序遍历的一种。
通常, “自底向上” 的递归函数 bottom_up(root) 为如下所示:
1. return specific value for null node
2. left_ans = bottom_up(root.left) // call function recursively for left child
3. right_ans = bottom_up(root.right) // call function recursively for right child
4. return answers
让我们继续讨论前面关于树的最大深度的问题,但是使用不同的思维方式:
对于树的单个节点,以节点自身为根的子树的最大深度x是多少?
如果我们知道一个根节点,以其左子节点为根的最大深度为l和以其右子节点为根的最大深度为r,我们是否可以回答前面的问题?
当然可以,我们可以选择它们之间的最大值,再加上1来获得根节点所在的子树的最大深度。
那就是 x = max(l,r)+ 1。
这意味着对于每一个节点来说,我们都可以在解决它子节点的问题之后得到答案。
因此,我们可以使用“自底向上“的方法。
下面是递归函数 maximum_depth(root) 的伪代码:
return 0 if root is null // return 0 for null node
2. left_depth = maximum_depth(root.left)
3. right_depth = maximum_depth(root.right)
4. return max(left_depth, right_depth) + 1 // return depth of the subtree rooted at root
C++代码
int maximum_depth(TreeNode* root) {
if (!root) {
return 0; // return 0 for null node
}
int left_depth = maximum_depth(root->left);
int right_depth = maximum_depth(root->right);
return max(left_depth, right_depth) + 1; // return depth of the subtree rooted at root
}
二叉树的最大深度
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL)
return 0;
int left_depth = maxDepth(root->left);
int right_depth = maxDepth(root->right);
return max(left_depth,right_depth)+1;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int ans = 0 ;
int maxDepth(TreeNode* root) {
int dep = 1;
helper(root , dep);
return ans;
}
void helper(TreeNode* root ,int depth)
{
if(root == NULL)
return ;
if (root->right == NULL && root->left == NULL)
ans = max(ans , depth);
if(root->right != NULL)
helper(root->right,depth+1);
if (root-> left != NULL)
helper(root->left, depth+1);
}
};
对称二叉树
最初想法是,通过中序遍历,看中序遍历向量的是否首尾相等。
但是代码没有通过所有测试
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
vector<int> ans;
inorder(root,ans);
int back = ans.size();
for(int i = 0; i <= back/2 ; i++)
{
cout << ans[i] << endl;
if(ans[i] != ans[back-i-1])
return false;
}
return true;
}
void inorder( TreeNode* root, vector<int> &order )
{
if(root == NULL)
{
return;
}
if (root->left != NULL){
inorder(root->left,order);
}
order.push_back(root->val);
if(root->right != NULL){
inorder(root->right,order);
}
}
};
转换想法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root == NULL)
return true;
return helper(root->left , root->right);
}
bool helper (TreeNode* A,TreeNode* B)
{
if ( A == NULL && B == NULL)
return true;
if (A == NULL || B == NULL)
return false;
if (A->val != B->val)
return false;
return (helper(A->right,B->left)&&helper(A->left,B->right));
}
};
路径总和
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
return helper(root,sum);
}
bool helper(TreeNode* cur, int sum)
{
if (cur == NULL)
return false;
if( cur->val == sum && cur->left == NULL && cur->right == NULL)
return true;
return (helper(cur->left , sum - cur->val) || helper(cur->right,sum - cur->val) );
}
};
逻辑:求二叉树的所有路径中,是否有与目标值相等的值
- 从上而下,当走到叶子节点的时候,检测是否为目标值
LeetCode--二叉树2--运用递归解决树的问题的更多相关文章
- LeetCode刷题笔记-递归-反转二叉树
题目描述: 翻转一棵二叉树. 解题思路: 1.对于二叉树,立马递归 2.先处理 根节点,不需改动 3.处根的左子树和右子树需要交换位置 4.递归处理左子树和右子树.步骤见1-3步 Java代码实现: ...
- leetcode二叉树题目总结
leetcode二叉树题目总结 题目链接:https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/ 前序遍历(NLR) p ...
- LeetCode Same Tree (判断相同树)
题意:如题 思路:递归解决,同判断对称树的原理差不多.先保证当前两个结点是相等的,再递归保证两左结点是相等的,再递归保证右结点是相等的. /** * Definition for a binary t ...
- 二叉树3种递归和非递归遍历(Java)
import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...
- 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)
初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵:若有不足,望大家批评指正. 进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的 ...
- K:二叉树的非递归遍历
相关介绍: 二叉树的三种遍历方式(先序遍历,中序遍历,后序遍历)的非递归实现,虽然递归方式的实现较为简单且易于理解,但是由于递归方式的实现受其递归调用栈的深度的限制,当递归调用的深度超过限制的时候, ...
- ZT 二叉树的非递归遍历
ZT 二叉树的非递归遍历 二叉树的非递归遍历 二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就 是递归定 ...
- LeetCode二叉树实现
LeetCode二叉树实现 # 定义二叉树 class TreeNode: def __init__(self, x): self.val = x self.left = None self.righ ...
- 二叉树遍历,递归,栈,Morris
一篇质量非常高的关于二叉树遍历的帖子,转帖自http://noalgo.info/832.html 二叉树遍历(递归.非递归.Morris遍历) 2015年01月06日 | 分类:数据结构 | 标 ...
随机推荐
- 远程关机 (Windows shutdown Windows)
在某些场景,可使用远程关机控制整个局域网中的所有电脑进行一键关机或重启,便于管理,以提高工作效率. 从远程系统强制关机,首先需要进行一些必要的设置. 1.使用 win + R 打开运行,输入gpedi ...
- Servlet中转发和重定向的路径问题以及表单提交路径问题
一.请求转发与响应重定向的种类 有两种方式获得Servlet转发对象(RequestDispatcher):一种是通过HttpServletRequest的getRequestDispatcher() ...
- iTOP-4418开发板_重实力_优势突出_有原理图源码开源
核心板参数 尺寸:50mm*60mm 高度:核心板连接器组合高度1.5mm PCB层数:6层PCB沉金设计 4418 CPU:ARM Cortex-A9 四核 S5P4418处理器 1.4GHz 68 ...
- 吴裕雄--天生自然python学习笔记:python 用firebase实现英文电子词典
Firebase 版电子词典 学英语是许多 人一辈子的麻烦 . 所以本例中,我们开发一个英汉词典,用户执 行程序后,单击“翻译”按钮即可显示该单词的中文翻译 . 英汉词典标准版 因为这个案例的数据必须 ...
- AppCompatActivity 透明背景
<!-- 背景透明样式 --> <style name="AppTheme.transparent" parent="Theme.AppCompat.L ...
- 一、SpringBoot学习笔记_Eclipse 安装 SpringBoot、配置Gradle
首先查看Eclipse 的版本 点击Help ,然后在点击About 就会出现下面的图片 去官网下载对应版本的SpringBoot插件压缩包,下载保存到能找到的位置 然后 点击 Help Inst ...
- Session深入浅出
Session会在浏览器关闭后消失吗? 通常情况下,当我们关闭浏览器再重新打开后,我们就需要再次进行登陆(如果没有进行下次自动登录之类的设置).在Jav中(Session是通用的,这里以Java为例) ...
- Java后台及Jsp前端的简单分页_学习笔记
在你需要导出显示大量列表时,在一页中都显示出来,是不美观页不实用的.在这种时候,就需要设置一个分页来显示你的内容,如百度的分页: 分页分为:前段分页和后端分页 后端分页: 首先我们应该确定,我们要分页 ...
- SQL语言:DDL,DML,DCL,DQL,TCL
DDL(Data Definition Language)数据库定义语言 statements are used to define the database structure or schema. ...
- mysql数据库常用命令入门
查询所有数据库 show databases; 创建数据库 create database mytest001 default character set utf8; 查看数据库的默认字符集 show ...