二叉树-路径(前序)

112. 路径总和

 1 class Solution {
 2     public boolean hasPathSum(TreeNode root, int sum) {
 3         if(root==null){
 4             return false;
 5         }
 6         if(sum==root.val && root.left==null && root.right==null){ //有个叶子结点的约束
 7             return true;
 8         }
 9         return hasPathSum(root.left, sum-root.val)
10         || hasPathSum(root.right, sum-root.val);
11     }
12 }

113. 路径总和 II    面试题34. 二叉树中和为某一值的路径

 1 class Solution {
 2     public List<List<Integer>> pathSum(TreeNode root, int sum) {
 3         List<List<Integer>> res = new ArrayList<>();
 4         // if(root==null){
 5         //     return res;
 6         // }
 7         findPath(root, sum, new ArrayList<>(), res);
 8         return res;
 9     }
10     public void findPath(TreeNode node, int sum, List<Integer> cur, List<List<Integer>> res){
11         if(node==null){
12             return;
13         }
14         cur.add(node.val);
15         if(node.val==sum && node.left==null && node.right==null){
16             res.add(cur);
17             return;
18         }
19         findPath(node.left, sum-node.val, new ArrayList<>(cur), res);
20         findPath(node.right, sum-node.val, new ArrayList<>(cur), res);
21     }
22 }
 1 class Solution {
 2     public List<List<Integer>> pathSum(TreeNode root, int sum) {
 3         List<List<Integer>> res = new ArrayList<>();
 4         // if(root==null){
 5         //     return res;
 6         // }
 7         findPath(root, sum, new Stack<>(), res);
 8         return res;
 9     }
10     public void findPath(TreeNode node, int sum, Stack<Integer> cur, List<List<Integer>> res){
11         if(node==null){
12             return;
13         }
14         cur.push(node.val);
15         if(node.val==sum && node.left==null && node.right==null){
16             res.add(new ArrayList<>(cur));
17             // return;  //加上return会有问题,会导致这个结点不被pop
18         }
19         // 可以加入左右子是否为空的判断,但加不加都行,反正进到函数里面也会判空
20         findPath(node.left, sum-node.val, cur, res);
21         findPath(node.right, sum-node.val, cur, res);
22         cur.pop();
23     }
24 }

注:思路1比较好想,但是比较费空间;思路2和cousin那道题很像,注意对比理解

(1)找到路径就放入res;否则找左右子,找完左右子,pop出当前结点==>也就是以这个结点为root的子树遍历完了,把这个结点pop,不要占用list。

(2)cousin:找到结点就return,因为路径唯一;否则找左右子,找完左右子也pop当前结点==>也就是以这个结点为root的子树遍历完了。

437. 路径总和 III  ?? 非常容易出错

 1 class Solution {
 2     public int count = 0;  // 常量类型只能提出来,和list不同,因为每次传参都不一是一个对象
 3     public int pathSum(TreeNode root, int sum) {
 4         if(root==null){
 5             return count;
 6         }
 7         findPath(root, sum);
 8         pathSum(root.left, sum);
 9         pathSum(root.right, sum);
10         return count;
11     }
12     public void findPath(TreeNode node, int cur){
13         if(node==null){
14             return;
15         }
16         if(node.val == cur){
17             count+=1;
18         }
19         findPath(node.left, cur-node.val);
20         findPath(node.right, cur-node.val);
21     }
22 }

理解:

pathSum:以当前结点作为起始结点找路径;并且分别把左右子结点作为根,计算子树的路径。---因为题目要求起始结点不一定是root

findPath:单纯找路径。

下面是错误解法,很容易陷入重复调用:

 1 class Solution {
 2     public int count = 0;  // 常量类型只能提出来,和list不同,因为每次传参都不一是一个对象
 3     public int pathSum(TreeNode root, int sum) {
 4         findPath(root, sum, sum);
 5         return count;
 6     }
 7     public void findPath(TreeNode node, int cur, int sum){
 8         if(node==null){
 9             return;
10         }
11         if(node.val == cur){
12             count+=1;
13         }
14         findPath(node.left, cur-node.val, sum);  //(1)
15         findPath(node.right, cur-node.val, sum);
16         findPath(node.left, sum, sum);   // (2)
17         findPath(node.right, sum, sum);
18     }
19 

993. 二叉树的堂兄弟节点

 1 class Solution {
 2     public boolean isCousins(TreeNode root, int x, int y) {
 3         if(root==null){
 4             return false;
 5         }
 6         Stack<Integer> stack1 = new Stack<>();
 7         Stack<Integer> stack2 = new Stack<>();
 8         findPath(root, x, stack1);
 9         findPath(root, y, stack2);
10         stack1.pop();
11         stack2.pop();
12         return stack1.size()==stack2.size() && stack1.pop()!=stack2.pop();
13     }
14     public boolean findPath(TreeNode node, int val, Stack<Integer> stack){
15         if(node==null){
16             return false;
17         }
18         stack.push(node.val);
19         if(node.val == val){
20             return true;
21         }else{
22             if(findPath(node.left, val, stack)){
23                 return true;
24             }
25             if(findPath(node.right, val, stack)){
26                 return true;
27             }
28             stack.pop();  // 注意
29             return false;
30         }
31     }
32 }

注:这道题本质就是一个查找路径问题,利用递归的思想查找路径。还有另一种解法,用两个map分别存储结点的父结点和层数,之后做对比,这种解法时间复杂度和空间复杂度都更小,因为是查一遍。但是第一种解法感觉更具普适性,保存路径的操作很多题都会用到。

 1 class Solution {
 2     public boolean isCousins(TreeNode root, int x, int y) {
 3         if(root==null){
 4             return false;
 5         }
 6         Map<Integer,TreeNode> father = new HashMap<>();
 7         Map<Integer,Integer> layer = new HashMap<>();
 8         Stack<Integer> stack2 = new Stack<>();
 9         findNode(root, null, father, layer);
10         return layer.get(x)==layer.get(y) && !father.get(x).equals(father.get(y));
11     }
12     public void findNode(TreeNode node, TreeNode par, Map<Integer,TreeNode> father, Map<Integer,Integer> layer){
13         if(node==null){
14             return;
15         }
16         int lay = par != null ? 1 + layer.get(par.val) : 0;
17         father.put(node.val, par);
18         layer.put(node.val, lay);
19         findNode(node.left, node, father, layer);
20         findNode(node.right, node, father, layer);
21     }
22 }

也可以把两个map定义为类成员变量,省的传来传去;father也可以用只保存val,都行。

面试题 04.08. 首个共同祖先

687. 最长同值路径

原文地址:https://www.cnblogs.com/naonaoling/p/12362887.html

时间: 2024-10-31 08:49:28

二叉树-路径(前序)的相关文章

根据二叉树的前序遍历和中序遍历重建二叉树

题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 1 /** 2 * Definition for binary tree 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(

二叉树各种相关操作(建立二叉树、前序、中序、后序、求二叉树的深度、查找二叉树节点,层次遍历二叉树等)(C语言版)

将二叉树相关的操作集中在一个实例里,有助于理解有关二叉树的相关操作: 1.定义树的结构体: 1 typedef struct TreeNode{ 2 int data; 3 struct TreeNode *left; 4 struct TreeNode *right; 5 }TreeNode; 2.创建根节点: 1 TreeNode *creatRoot(){ 2 TreeNode * root =(TreeNode *)malloc(sizeof(TreeNode)); 3 if(NULL=

二叉树的前序、中序、后序遍历的递归和非递归算法实现

1 /** 2 * 二叉树的前序.中序.后序遍历的递归和非递归算法实现 3 **/ 4 5 //二叉链表存储 6 struct BTNode 7 { 8 struct BTNode *LChild; // 指向左孩子指针 9 ELEMENTTYPE data; // 结点数据 10 struct BTNode *RChild; // 指向右孩子指针 11 }; 12 13 /** 14 * 前序遍历 15 **/ 16 // 递归实现 17 void PreorderTraversal(BTNo

Leetcode:Path Sum 二叉树路径和

Path Sum: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example:Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ 7 2 1 return

笔试算法题(06):最大连续子数组和 &amp; 二叉树路径和值

出题:预先输入一个整型数组,数组中有正数也有负数:数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和:求所有子数组中和的最大值,要求时间复杂度O(n): 分析: 时间复杂度为线性表明只允许一遍扫描,当然如果最终的最大值为0表明所有元素都是负数,可以用线性时间O(N)查找最大的元素.具体算法策略请见代码和注释: 子数组的起始元素肯定是非负数,如果添加的元素为正数则记录最大和值并且继续添加:如果添加的元素为负数,则判断新的和是否大于0,如果小于0则以下一个元素作为起始元素重新开始,如果大于

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

问题描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 思路: 在二叉树的前序遍历序列中,第一个数字总是树的根结点的值.但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边.因此我们需要扫描中序遍历序列,才能找到根结点的值. 如下图所示,

二叉树的前序中序后序遍历相互求法

二叉树的前中后序遍历,他们的递归非递归.还有广度遍历,参见二叉树的前中后序遍历迭代&广度遍历和二叉树的前中后序遍历简单的递归 现在记录已知二叉树的前序中序后序遍历的两个,求另外一个.一般,这两个中一定有中序遍历. 1.已知前序和中序,求后序遍历: 前序:ABDECFG  中序:DBEAFCG 思路简单:前序的第一个节点就是根节点, 中序中找到根节点的位置,根节点之前是其左子树,之后是右子树   按此顺序,依次在左子树部分遍历,右子树部分遍历 C++ 代码: TreeNode *BinaryTre

hihocoder(第十周)二叉树(前序中序推后续)递推实现

题目 : 后序遍历 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在参与过了美食节之后,小Hi和小Ho在别的地方又玩耍了一阵子,在这个过程中,小Ho得到了一个非常有意思的玩具——一棵由小球和木棍连接起来的二叉树! 小Ho对这棵二叉树爱不释手,于是给它的每一个节点都标记了一个标号——一个属于A..Z的大写字母,并且没有任意两个节点的标号是一样的.小Hi也瞅准了这个机会,重新巩固了一下小Ho关于二叉树遍历的基础知识~就这样,日子安稳的过了两天. 这天,小Ho正好在求解

已知二叉树的前序遍历结果和中序遍历结果,请重建原来的二叉树

分析的过程: 1.假设前序遍历的第一个值为a,该值就是原二叉树的根节点. 2.在中序遍历结果中查找a. 则在中序遍历中a前面的节点,就是原二叉树a节点左子树的中序遍历结果:在a后面的节点,就是原二叉树a节点右子树的中序遍历结果. 3.由第二步得到a节点左子树的节点个数为m,那么在前序遍历中a后面的m个节点即为a节点左子树的前序遍历结果: 4.由第二步得到a节点右子树的节点个数为n,那么在前序遍历中最后n个节点即为a节点右子树的前序遍历结果: 由此我们可以得到a节点左子树和右子树的前序遍历和中序遍

二叉树的前序、中序、后序遍历(递归、非递归)实现

本文部分来源于CSDN兰亭风雨大牛的原创.链接为http://blog.csdn.net/ns_code/article/details/12977901 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的.二叉树有前.中.后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但其开销也比较大,而若采用非递归方法实现三种遍历,则要用栈来模拟实现(递归也是用栈实现的).下面先简要介绍三种遍历方式的递归实现,再详细介绍三种遍