Leetcode中二叉树中的搜索相关题目解析以及java实现(第二篇)
接上一篇,继续看二叉树中的搜索的相关问题和java的实现。
- [236] Lowest Common Ancestor of a Binary Tree
- [156] Binary Tree Upside Down:
- [617] Merge Two Binary Trees:
- [654] Maximum Binary Tree:
- [563] Binary Tree Tilt:
让我们开始吧!
[236] Lowest Common Ancestor of a Binary Tree
这一题其实非常的有意思,因为有三种不同的变种,先看原题,给出两个在同一个二叉树的两个子节点,让我们寻找这两个子节点的最近的共同父节点,这一题我们用分治法递归来解决,从根节点开始向下递归查找,如果找到了目标子节点就直接返回,如果当前的节点下可以同时找到两个子节点时就直接返回当前节点。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p ||root == q){
return root;
}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left != null && right != null){
return root;
}
if(left != null){
return left;
}
if(right != null){
return right;
}
return null;
}
}
另外一种就是当前二叉树的节点里给出了父节点,虽然我们也可以用上一种解法来解决,但是我们同样也可以用非递归的方法来实现。
就利用目标节点的父节点指针来记录走向根节点的路径,然后前向后进行比对,最后一个相同的节点就是两个子节点的LCA
public class solution{
public TreeNode lowestCommonAncestor(TreeNode root,TreeNode p,TreeNode q){
ArrayList<TreeNode> pathA = getPath(p);
ArrayList<TreeNode> pathB = getPath(q);
TreeNode result = null;
indexA = pathA.length()-1;
indexB = pathB.length()-1;
while(indexA >=0 && indexB >= 0){
if(pathA.get(indexA) != pathB.get(indexB)){
break;
}
result = pathA.get(indexA);
indexA--;
indexB--;
}
return result;
}
private ArrayList<TreeNode> getPath(TreeNode node){
ArrayList<TreeNode> result = new ArrayList<>();
while(node != null){
result.add(node);
node = node.parent;
}
return result;
}
}
还有一种不一样的可能性那就是这两个给定的节点并不在同一个树内,这个时候我们就要利用多个返回值+分治法来解决这个问题。
public class solution{
class ResultType{
public boolean a_exist, b_exist;
public TreeNode node;
public ResultType(boolean a,boolean b,TreeNode node){
this.a_exist = a;
this.b_exist = b;
this.node = node;
}
}
public TreeNode LCA3(TreeNode root,TreeNode a,TreeNode b){
ResultType result = helper(root,a,b);
return result.node;
}
public ResultType helper(TreeNode root,TreeNode a, TreeNode b){
if(root == null){
return new ResultType(false,false,null);
}
ResultType left = helper(root.left,a,b);
ResultType right = helper(root.right,a,b);
boolean a_exist = left.a_exist||right.a_exist||root == a;
boolean b_exist = left.b_exist||right.b_exist||root == b;
if(root == a||root == b){
return new ResultType(a_exist,b_exist,root);
}
if(left.node != null && right.node != null){
return new ResultType(a_exist,b_exist,root);
}
if(left.node == null && right.node != null){
return new ResultType(a_exist,b_exist,right.node);
}
if(left.node != null && right.node == null){
return new ResultType(a_exist,b_exist,left.node);
}
return new ResultType(a_exist,b_exist,null);
}
}
[156] Binary Tree Upside Down:
翻转一棵二叉树,当然题目也给出了限制那就是每一个节点要么就没有右子节点,要么就有两个节点,其实就相当于是把当前的二叉树进行了顺时针的调转,当前的右子节点变成了左子节点,左子节点变成了根节点,根节点变成了右子节点。同样我们也是不断的递归走到最左的子节点,当最左的子节点反转完毕之后我们就翻转当前的节点。
class Solution{
public TreeNode upsideDownBinaryTree(TreeNode root){
if(root == null || root.left == null) return root;
TreeNode left = root.left;
TreeNode right = root.right;
TreeNode result = upsideDownBinaryTree(left);
left.left = right;
left.right = root;
root.left = null;
root.right = null;
return result;
}
}
Merge two binary Tree
这一题其实就比较简单了,难度标的也是easy,就把两个二叉树重叠起来,共有的节点就相加,不共有的就直接复制。同样我们用递归来解决这个问题。
class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if(t1 == null)return t2;
if(t2 == null)return t1;
int val = t1.val +t2.val;
TreeNode root = new TreeNode(val);
TreeNode left = mergeTrees(t1.left,t2.left);
TreeNode right = mergeTrees(t1.right,t2.right);
root.left = left;
root.right = right;
return root;
}
}
Maximum binary Tree
输入一个数组,根据这个数组构建一个根节点最大的二叉树,左子节点是当根节点值左边最大的值,右节点则刚好相反,一样我们利用分治法来解决这个问题
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums == null || nums.length == 0)return null;
int maxid = 0;
int max = Integer.MIN_VALUE;
for(int i = 0;i < nums.length;i++){
if(nums[i] > max){
max = nums[i];
maxid = i;
}
}
TreeNode root = new TreeNode(max);
TreeNode left = constructMaximumBinaryTree(Arrays.copyOfRange(nums,0,maxid));
TreeNode right = constructMaximumBinaryTree(Arrays.copyOfRange(nums,maxid+1,nums.length));
root.left = left;
root.right = right;
return root;
}
}
Binary Tree Tilt
这道题让我们求二叉树的坡度,某个结点的坡度的定义为该结点的左子树之和与右子树之和的差的绝对值,然后最后返回的值就是整颗二叉树的坡度的合,利用后序遍历的特性来解决这个问题,可以先计算左右,再计算根节点的值。
class Solution {
int res = 0;
public int findTilt(TreeNode root) {;
postOrder(root);
return res;
}
private int postOrder(TreeNode node){
if(node == null)return 0;
int leftSum = postOrder(node.left);
int rightSum = postOrder(node.right);
res += Math.abs(leftSum-rightSum);
return leftSum+rightSum+node.val;
}
}
这一部分的题基本上都可以用分治法和递归来完成