大家好我是苏麟 , 今天来说二叉树的经典题目
二叉树的双指针
所谓的双指针就是定义了两个变量,在二叉树中有时候也需要至少定义两个变量才能解决问题,这两个指针可能针对一棵树,也可能针对两棵树,我们姑且也称之为“双指针”吧。这些问题一般是与对称、反转和合并等类型相关,我们接下来就看一下相关高频问题。
判断两棵树是否相同
描述 :
给你两棵二叉树的根节点 p
和 q
,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
题目 :
LeetCode 100.相同的树 :
分析 :
这个貌似就是两个二叉树同时进行前序遍历,先判断根节点是否相同,如果相同再分别判断左右子节点是否相同,判断的过程中只要有一个不相同就返回 false,如果全部相同才会返回true。
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null){
return true;
}
if(p == null || q == null ){
return false;
}
if(p.val != q.val){
return false;
}
return isSameTree(p.left,q.left) && isSameTree(p.right ,q.right);
}
}
对称二叉树
描述 :
给你一个二叉树的根节点 root
, 检查它是否轴对称。
题目:
LeetCode 101.对称二叉树
分析:
我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等 .
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null){
return true;
}
TreeNode p = root;
TreeNode q = root;
return is(p,q);
}
public boolean is(TreeNode left ,TreeNode right){
if(left == null && right == null){
return true;
}
if((left != null && right == null) ||( right != null && left ==null)){
return false;
}
if(left.val != right.val){
return false;
}
return is(left.left,right.right) && is(left.right,right.left);
}
}
合并二叉树
描述 :
给你两棵二叉树: root1
和 root2
。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
题目 :
LeetCode 617.合并二叉树
分析 :
两个二叉树的对应节点可能存在以下三种情况,对于每种情况使用不同的合并方式
- 如果两个二又树的对应节点都为空,则合并后的二又树的对应节点也为空
- 如果两个二又树的对应节点只有一个为空,则合并后的二又树的对应节点为其中的非空节点
- 如果两个二叉树的对应节点都不为空,则合并后的二叉树的对应节点的值为两个二叉树的对应节点的值之和,此时需要显性合并两个节点。
对一个节点进行合并之后,还要对该节点的左右子树分别进行合并
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1 == null){
return root2;
}
if(root2 == null){
return root1;
}
TreeNode node = new TreeNode(root1.val + root2.val);
node.left = mergeTrees(root1.left,root2.left);
node.right = mergeTrees(root1.right,root2.right);
return node;
}
}
路径专题
关于二又树有几道与路径有关的题目,我们统一看一下。初次接触你会感觉有些难,但是这是在为回溯打基础,因为很多回溯问题就是在找路径,甚至要找多条路径。
二叉树的所有路径
描述 :
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
题目:
LeetCode 257.二叉树的所有路径 :
分析 :
有几个叶子节点,就有几条路径,那如何找叶子节点呢? 我们知道深度优先搜索就是从根节点开始一直找到叶子结点,我们这里可以先判断当前节点是不是叶子结点,再决定是不是向下走,如果是叶子结点,我们就增加一条路径 . 增加一个String类型的变量, 先存到String中,到叶子节点的时候再添加到集合里 :
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> list = new ArrayList<>();
allPath(root,"",list);
return list;
}
public void allPath(TreeNode root ,String s, List<String> list){
if(root == null){
return;
}
if((root.left == null) && (root.right == null)){
s += root.val;
list.add(s);
return;
}
s = s + root.val + "->";
allPath(root.left,s,list);
allPath(root.right,s,list);
}
}
路径总和
描述 :
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
题目:
LeetCode 112.路径总和 :
分析 :
这道题跟上面的很像 , 这里只需要一个变量来记录总和就可以了 , 其他步骤都是一样的 .
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
return allNum(root,0,targetSum);
}
public boolean allNum(TreeNode root,int num,int targetSum){
if(root == null){
return false;
}
if(root.left == null && root.right == null){
num += root.val;
if(targetSum == num){
return true;
}
return false;
}
num += root.val;
boolean p = allNum(root.left,num,targetSum);
boolean q =allNum(root.right,num,targetSum);
return p || q;
}
}
翻转
描述 :
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
题目 :
LeetCode 226.翻转二叉树 :
分析 :
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始 , 可以创建新的节点连接 也可以 翻转 .
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode invertTree(TreeNode root) {
return reverse(root);
}
public TreeNode reverse(TreeNode root){
if(root == null){
return null;
}
TreeNode node = new TreeNode(root.val);
node.left = reverse(root.right);
node.right = reverse(root.left);
return node;
}
}
这期就到这里 , 下期见!