1. 二叉树里的双指针
双指针
就是定义两个变量,在二叉树中有时候也需要定义两个变量才能解决问题,这两个指针可能针对一棵树,也可能针对两棵树,姑且也称之为双指针
!
1.1 判断两棵树是否相同
LeetCode100: 判断两棵树是否相同
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
输入:p = [1,2,3],q=[1,2,3]
输出:true
解题思路:
1.类似于两个二叉树同时进行前序遍历,先判断根节点是否相同,如果相同再分别判断左右子节点是否相同,判断的过程中只要有一个不相同就返回false,如果全部相同就返回ture。
代码如下:
public boolean isSameTree(TreeNode p, TreeNode q) {
//如果都为空,就是相同的
if (p == null && q == null) {
return true;
}
//如果一个为空,一个不为空,很明显是不可能是相同的树,直接返回false
if (p == null || q == null) {
return false;
}
//如果对应位置的两个结点的值不相等,自然也不是同一棵数
if (p.val != q.val) {
return false;
}
//走到这一步说明节点p和q是完全相同的,接下来需要再判断其左和右是否满住要求
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
1.2 对称二叉树
LeetCode101: 对称二叉树:给你一个二叉树的根节点 root , 检查它是否轴对称。
解题思路:
通过递归的返回值来判断两个子树的内侧结点和外侧结点是否相等,所以准确的来说是一个树的遍历顺序左中右,一个树的遍历顺序是右左中。
1.比较二叉树外侧是否对称:传入的左节点的左孩子,右节点的右孩子
2.比较 内侧是否对称,传入左节点的右孩子,右节点的左孩子。
3.如果左右都对称返回true,有一侧不对称就返回false。
代码如下:
public boolean isSymmetric(TreeNode node){
if (node == null){
return true;
}
return check(node.left,node.right);
}
public boolean check(TreeNode p,TreeNode q){
if (p == null && q == null){
return true;
}
if (p == null || q == null){
return false;
}
return p.val == q.val && check(p.left,q.right) && check(p.right,q.left);
}
1.3 合并二叉树
LeetCode617 合并二叉树:
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
输入:root1 = [1,3,2,5],root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]
两个二叉树的队友节点可能存在以下三种情况,对应每种情况使用不同的合并方式。
- 如果两个二叉树的对应节点都为空,则合并后的二叉树的对应节点也为空;
- 如果两个二叉树的对应节点只有一个为空,则合并后的二叉树的对应节点为其中的非空节点;
- 如果两个二叉树的对应节点都不为空,则合并后的二叉树的对应节点的值为两个二叉树的对应节点的值之和,此时需要显性合并两个节点。
对一个节点进行合并之后,还要对该节点的左右子树分别进行合并。
代码如下:
public TreeNode mergeTrees(TreeNode t1,TreeNode t2){
if (t1 == null){
return t2;
}
if (t2 == null){
return t1;
}
TreeNode merged = new TreeNode(t1.val + t2.val);
merged.left = mergeTrees(t1.left,t2.left);
merged.right = mergeTrees(t1.right,t2.right);
return merged;
}