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) );
}
};

逻辑:求二叉树的所有路径中,是否有与目标值相等的值

  1. 从上而下,当走到叶子节点的时候,检测是否为目标值

LeetCode--二叉树2--运用递归解决树的问题的更多相关文章

  1. LeetCode刷题笔记-递归-反转二叉树

    题目描述: 翻转一棵二叉树. 解题思路: 1.对于二叉树,立马递归 2.先处理 根节点,不需改动 3.处根的左子树和右子树需要交换位置 4.递归处理左子树和右子树.步骤见1-3步 Java代码实现: ...

  2. leetcode二叉树题目总结

    leetcode二叉树题目总结 题目链接:https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/ 前序遍历(NLR) p ...

  3. LeetCode Same Tree (判断相同树)

    题意:如题 思路:递归解决,同判断对称树的原理差不多.先保证当前两个结点是相等的,再递归保证两左结点是相等的,再递归保证右结点是相等的. /** * Definition for a binary t ...

  4. 二叉树3种递归和非递归遍历(Java)

    import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...

  5. 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)

    初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵:若有不足,望大家批评指正. 进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的 ...

  6. K:二叉树的非递归遍历

    相关介绍:  二叉树的三种遍历方式(先序遍历,中序遍历,后序遍历)的非递归实现,虽然递归方式的实现较为简单且易于理解,但是由于递归方式的实现受其递归调用栈的深度的限制,当递归调用的深度超过限制的时候, ...

  7. ZT 二叉树的非递归遍历

    ZT 二叉树的非递归遍历 二叉树的非递归遍历 二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就 是递归定 ...

  8. LeetCode二叉树实现

    LeetCode二叉树实现 # 定义二叉树 class TreeNode: def __init__(self, x): self.val = x self.left = None self.righ ...

  9. 二叉树遍历,递归,栈,Morris

    一篇质量非常高的关于二叉树遍历的帖子,转帖自http://noalgo.info/832.html 二叉树遍历(递归.非递归.Morris遍历) 2015年01月06日 |  分类:数据结构 |  标 ...

随机推荐

  1. Opencv笔记(十六)——认识轮廓

    什么是轮廓? 轮廓可以简单认为成连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度.轮廓在形状分析和物体的检测和识别中很有用.谈起轮廓不免想到边缘,它们确实很像.简单的说,轮廓是连续的,边缘并 ...

  2. tesseract系列(1) -- tesseract用vs编译成库

    1.下载teseract 下载地址github:     https://github.com/tesseract-ocr/tesseract/releases/ 2.编译源码 源码的编译有两种方式 ...

  3. Pay Back(模拟)

    链接:https://ac.nowcoder.com/acm/contest/1086/C 题目描述 "Never a borrower nor a lender be." O h ...

  4. VMware安装 RHEL安装完后,选择桥接模式如何与主机网络连通

    .查看主机的ip与网关,dns配置,如图 2.在linux系统中打开cd  /etc/sysconfig/network-scripts/  #进入网络配置文件目录 vi  ifcfg-eno1677 ...

  5. jquey ajax 将变量值封装json传入JAVA action获取解析

    最近在做一个小小的功能模块,前台有很多的数据需要传入到后台,前台页面设计如下: 看起来不是很清楚,总之表单中的数据都要提交到后台进行处理,然后插入到数据库,而且是一起提交到后台的,实现的方法大致有两种 ...

  6. python爬虫和数据分析、数据挖掘

    一.python爬虫脑图: 二.python爬虫流程: 三.python数据分析简介 四.python数据预处理方法 五.python数据挖掘 六.数据探索基础

  7. HTML配色表方案

  8. Contig|scaffold|N50|L50|NG50|贪心算法|de bruiji graph|

    生物信息学 Contig是reads拼成的连续的DNA片段,连续表达一个gene.通过双端测序的contig可确定contig之间的关系得到scaffold,Scaffold是reads拼成的有gap ...

  9. Qt QByteArray 与 char* 的转换

    QByteArray 转换为 char * char *ch;//不要定义成ch[n]; QByteArray byte; ch = byte.data(); char * 转换为 QByteArra ...

  10. 发现个很有意思的angularjs +grunt 复习项目

    最近作运维工作 docker 接触到一个开源webui dockerui 原项目地址 https://github.com/crosbymichael/dockerui 用angular框架实现,项目 ...