二叉树相关算法

1.合并二叉树

要求:
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

示例 :
输入: 
    Tree 1                     Tree 2                  
          1                         2                             
         / \                       / \                            
        3   2                     1   3                        
       /                           \   \                      
      5                             4   7                  
输出: 
合并后的树:
         3
        / \
       4   5
      / \   \ 
     5   4   7

注意: 合并必须从两个树的根节点开始。
//1.递归
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
        if (t1 == null)
            return t2;
        if (t2 == null)
            return t1;
        t1.val += t2.val;
        t1.left = mergeTrees(t1.left, t2.left);
        t1.right = mergeTrees(t1.right, t2.right);
        return t1;
    }
}

//2.迭代法
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
        if (t1 == null)
            return t2;
        Stack < TreeNode[] > stack = new Stack < > ();
        stack.push(new TreeNode[] {t1, t2});
        while (!stack.isEmpty()) {
            TreeNode[] t = stack.pop();
            if (t[0] == null || t[1] == null) {
                continue;
            }
            t[0].val += t[1].val;
            if (t[0].left == null) {
                t[0].left = t[1].left;
            } else {
                stack.push(new TreeNode[] {t[0].left, t[1].left});
            }
            if (t[0].right == null) {
                t[0].right = t[1].right;
            } else {
                stack.push(new TreeNode[] {t[0].right, t[1].right});
            }
        }
        return t1;
    }
}

2.翻转二叉树

要求:
翻转一棵二叉树。

示例:
输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9
输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1
//1.递归
public TreeNode invertTree(TreeNode root) {
    if (root == null) {
        return null;
    }
    TreeNode right = invertTree(root.right);
    TreeNode left = invertTree(root.left);
    root.left = right;
    root.right = left;
    return root;
}

//2.迭代
public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;
    Queue queue = new LinkedList();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode current = queue.poll();
        TreeNode temp = current.left;
        current.left = current.right;
        current.right = temp;
        if (current.left != null) queue.add(current.left);
        if (current.right != null) queue.add(current.right);
    }
    return root;
}

3.判断二叉树是不是镜像对称

要求:
给定一个二叉树,检查它是否是镜像对称的。

示例:
二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
  2   2
   \   \
   3    3
// 1.递归
public boolean isSymmetric(TreeNode root) {
    return isMirror(root, root);
}

public boolean isMirror(TreeNode t1, TreeNode t2) {
    if (t1 == null && t2 == null) return true;
    if (t1 == null || t2 == null) return false;
    return (t1.val == t2.val)
        && isMirror(t1.right, t2.left)
        && isMirror(t1.left, t2.right);
}

//2.迭代
public boolean isSymmetric(TreeNode root) {
    Queue q = new LinkedList<>();
    q.add(root);
    q.add(root);
    while (!q.isEmpty()) {
        TreeNode t1 = q.poll();
        TreeNode t2 = q.poll();
        if (t1 == null && t2 == null) continue;
        if (t1 == null || t2 == null) return false;
        if (t1.val != t2.val) return false;
        q.add(t1.left);
        q.add(t2.right);
        q.add(t1.right);
        q.add(t2.left);
    }
    return true;
}

4.二叉树的最大深度

要求:
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

示例:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 
  //1. 递归
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }

//2.迭代
public int maxDepth(TreeNode root) {
    if(root == null) {
        return 0;
    }
    Queue queue = new LinkedList<>();
    queue.offer(root);
    int count = 0;
    while(!queue.isEmpty()) {
        int size = queue.size();
        while(size-- > 0) {
            TreeNode node = queue.poll();
            if(node.left != null) {
                queue.offer(node.left);
            }
            if(node.right != null) {
                queue.offer(node.right);
            }
        }
        count++;
    }
    return count;
}

5.二叉树的层次遍历

5.1 二叉树的层次遍历(常规输出)

示例:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其层次遍历结果:

[3,9,20,15,7]
//1.递归
public void levelTraversal(TreeNode root){
    
}

//2.迭代
public static void levelTraversal(TreeNode root){
    if(root == null) {
        return;
    }
    Queue queue = new LinkedList<>(); // 对列保存树节点
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode temp = queue.poll();
        System.out.print(temp.val + "->");
        if (temp.left != null) { // 添加左右子节点到对列
            queue.add(temp.left);
        }
        if (temp.right != null) {
            queue.add(temp.right);
        }
    }
}

5.2.二叉树的层次遍历(变种输出)

要求:
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]
public class Solution {
    public List> levelOrder(TreeNode root) {
        Queue queue = new LinkedList();
        List> wrapList = new LinkedList>();
        
        if(root == null) return wrapList;
        
        queue.offer(root);
        while(!queue.isEmpty()){
            int levelNum = queue.size();
            List subList = new LinkedList();
            for(int i=0; i

6.相同的树

要求:
给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:
输入:       1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

输出: true

示例 2:
输入:       1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

输出: false
//1.递归
public boolean isSameTree(TreeNode p, TreeNode q) {
    if(p==null && q==null) return true;
    if(p==null || q==null) return false;
    return (p.val==q.val) && isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}

//2.迭代
  public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) return true;
        if(p==null || q==null) return false;
        Queue stackP = new LinkedList<>();
        Queue stackQ = new LinkedList<>();
        stackP.add(p);
        stackQ.add(q);
        while (!stackP.isEmpty() && !stackQ.isEmpty()) {
            TreeNode tmpP = stackP.poll();
            TreeNode tmpQ = stackQ.poll();
            if (tmpP.val != tmpQ.val) return false;
            if (tmpP.left != null && tmpQ.left != null) {
                stackP.add(tmpP.left);
                stackQ.add(tmpQ.left);
            } else if (tmpP.left == null && tmpQ.left == null) {
            } else {
                return false;
            }
            if (tmpP.right != null && tmpQ.right != null) {
                stackP.add(tmpP.right);
                stackQ.add(tmpQ.right);
            } else if (tmpP.right == null && tmpQ.right == null) {
            } else {
                return false;
            }
        }
        if (!stackP.isEmpty() || !stackQ.isEmpty()) return false;
        return true;
    }

7.平衡二叉树

要求:
给定一个二叉树,判断它是否是平衡的二叉树。

性质:
     1.它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1
     2.并且左右两个子树都是一棵平衡二叉树
  • 1.递归(时间复杂度O(n^2),先序遍历)

二叉树中的很多结点遍历了多次;
求解根的的高度时,需要先求解根的左子树高度和右子树高度,这就遍历了整棵左子树中的结点和右子树中的结点。而求解以根的左孩子为根的子树的高度时,又需要遍历它(根的左孩子)的左子树和右子树。这样,相当于很多结点的高度重复计算了。

    public boolean isBalanced(TreeNode root) {
        if(null == root) return true;
        int left = depth(root.left);
        int right = depth(root.right);
        return Math.abs(left - right) <= 1 && isBalanced(root.left) && isBalanced(root.right);
    }
    
    public int depth(TreeNode root){
        if(null == root) return 0;
        return Math.max(depth(root.left), depth(root.right)) + 1;
    }
  • 2.递归(时间复杂度O(n),后序遍历))

先知道某结点左右子树的高度,如果左右子树的高度都不满足平衡二叉树(二者高度相减大于1),那么都不需要再去求解该结点的高度了。

  public boolean isBalanced(TreeNode root) {
       return dfsHeight (root) != -1;
    }
   
    public int dfsHeight (TreeNode root){
        if (root == null) return 0;
        int leftHeight = dfsHeight (root.left);
        if(-1 == leftHeight) return -1;
        int rightHeight = dfsHeight(root.right);
        if(-1 == rightHeight) return -1;
        if(Math.abs(leftHeight - rightHeight) > 1) return -1;
        return Math.max(leftHeight,rightHeight) + 1;
    }

你可能感兴趣的:(二叉树相关算法)