二叉树里的双指针
所谓的双指针就是定义了两个变量,在二叉树中有时候也需要定义两个变量解决问题,这两个变量可能针对一棵树,也可能针对两棵树,我们称之为双指针。双指针用在对称、反转和合并等类型相关。
1. 判断两棵树是否相同
LeetCode100:给你两颗二叉树的跟节点p和q,编写一个函数类检验这两棵树是否相同,如果两棵树在结构上相同,并且节点具有相同的值,则认为他们是相同的。
思路:
就是两颗二叉树进行前序遍历,先判断根节点是否相同,如果相同再分别比较左右子节点是否相同,判断过程中有一个不相同就返回false,全部相同就返回true。
代码:
//判断两棵树是否相等,两个指针分别位于两棵树上
public boolean isSameTree(TreeNode p, TreeNode q) {
//如果都为空我们则认为他们是相同的
if (p == null && q == null) {
return true;
}
//如果一个为空一个不为空,则两树不相等,返回false
if (p == null || q == null) {
return false;
}
//如果两个位置值不相等那么也不是一颗二叉树
if (q.val != p.val) {
return false;
}
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
2. 对称二叉树
LeetCode:给定一颗二叉树,检查它是否是镜像对称的
思路:
通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相同,准确的说一个树遍历的顺序是左右中,一个树遍历顺序是右左中。
关键要关注如何比较和如何处理结束条件。
- 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
- 比较内侧是否对称,传入左结点的右孩子,右节点的左孩子。
- 如果左右都对称就返回true,有一侧不对称就返回false。
代码:
//对称二叉树,两个指针在同一颗树中
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return check(root.left, root.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);
}
3. 合并二叉树
LeetCode:给定两个二叉树,需要将他们合并为一个新的二叉树。合并规则是两个节点重合,将他们的值相加作为节点合并后的值,如果右一棵树的节点为null,则另一个不为null的节点直接作为二叉树的节点。
合并两个二叉树相对应的节点会出现三种情况,对于每种情况使用不同的合并方式。
- 如果两个二叉树的对应节点都为null,则合并后的二叉树的对应节点也为空。
- 如果两个二叉树的对应节点只有一个为null,则合并后对应的节点为其中的非空节点。
- 如果两个二叉树的节点不为空,则合并后的新节点的值,为两个对应节点值的和。
代码:
//合并二叉树,两个指针分别在两颗树中
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
/**
* 如果两个对应的结点都是空,则合并后的也是空
* 一个为空则合并后的是另一个,两个都为null则直接返回null
*/
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;
}