牛客网【面试必刷TOP101】~ 03二叉树

牛客网【面试必刷TOP101】~ 03二叉树

文章目录

    • 牛客网【面试必刷TOP101】~ 03二叉树
    • @[toc]
      • BM23 二叉树的前序遍历(★)
      • BM24 二叉树的中序遍历(★★)
      • BM25 二叉树的后序遍历(★)
      • BM26 求二叉树的层序遍历(★★)
      • BM27 按之字形顺序打印二叉树(★★)
      • BM28 二叉树的最大深度(★)
      • BM29 二叉树中和为某一值的路径(一)(★)
      • BM30 二叉搜索树与双向链表(★★)
      • BM31 对称的二叉树(★)
      • BM32 合并二叉树(★)
      • BM33 二叉树的镜像(★)
      • BM34 判断是不是二叉搜索树(★★)
      • BM35 判断是不是完全二叉树(★★)
      • BM36 判断是不是平衡二叉树(★)
      • BM37 二叉搜索树的最近公共祖先(★)
      • BM38 在二叉树中找到两个节点的最近公共祖先(★★)
      • BM39 序列化二叉树(★★★)
      • BM40 重建二叉树(★★)
      • BM41 输出二叉树的右视图(★★)

BM23 二叉树的前序遍历(★)

方法一:递归(18ms)

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    private List<Integer> list;

    public int[] preorderTraversal (TreeNode root) {
        list = new ArrayList<Integer>();
        preorder(root);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

    private void preorder(TreeNode root) {
        if (root == null) return;
        list.add(root.val);
        preorder(root.left);
        preorder(root.right);
    }

}

方法二:栈(20ms)

public class Solution {
    private List<Integer> list;

    public int[] preorderTraversal (TreeNode root) {
        list = new ArrayList<Integer>();
        preorder(root);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

    private void preorder(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            list.add(node.val);
            if (node.right != null) stack.push(node.right);
            if (node.left != null) stack.push(node.left);
        }
    }

}

BM24 二叉树的中序遍历(★★)

方法一:递归(35ms)

public class Solution {
    private ArrayList<Integer> list;

    public int[] inorderTraversal (TreeNode root) {
        list = new ArrayList<Integer>();
        inorder(root);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

    private void inorder(TreeNode root) {
        if (root == null) return;
        inorder(root.left);
        list.add(root.val);
        inorder(root.right);
    }
}

方法二:栈(37ms)

public class Solution {
    private ArrayList<Integer> list;

    public int[] inorderTraversal (TreeNode root) {
        list = new ArrayList<Integer>();
        inorder(root);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

    private void inorder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            TreeNode node = stack.pop();
            list.add(node.val);
            root = node.right;
        }
    }

}

BM25 二叉树的后序遍历(★)

方法一:递归(20ms)

public class Solution {
    private ArrayList<Integer> list;
     
    public int[] postorderTraversal (TreeNode root) {
        list = new ArrayList<Integer>();
        postorder(root);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

    private void postorder(TreeNode root) {
        if (root == null) return;
        postorder(root.left);
        postorder(root.right);
        list.add(root.val);
    }
}

方法二:双栈(20ms)

public class Solution {
    private ArrayList<Integer> list;
     
    public int[] postorderTraversal (TreeNode root) {
        list = new ArrayList<Integer>();
        postorder(root);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

    private void postorder(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        Stack<Integer> help  = new Stack<Integer>();

        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            help.push(node.val);
            if (node.left  != null) stack.push(node.left);
            if (node.right != null) stack.push(node.right);
        }

        while (!help.isEmpty()) list.add(help.pop());
    }
}

BM26 求二叉树的层序遍历(★★)

方法一:递归(33ms)

public class Solution {
    private ArrayList<ArrayList<Integer>> res;
    
    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        res = new ArrayList();
        helper(root, 0);
        return res;
    }

    private void helper(TreeNode root, int deep) {
        if (root == null) return;
        if (res.size() <= deep) res.add(new ArrayList<Integer>());
        res.get(deep).add(root.val);
        helper(root.left, deep + 1);
        helper(root.right, deep + 1);
    }
}

方法二:队列(31ms)

public class Solution {
    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        if (root == null) return res;
        ArrayDeque<TreeNode> queue = new ArrayDeque<TreeNode>();
        
        queue.offer(root);
        while (!queue.isEmpty()) {
            int sz = queue.size();
            ArrayList<Integer> temp = new ArrayList<Integer>();
            for (int i = 0; i < sz; i++) {
                TreeNode node = queue.poll();
                temp.add(node.val);
                if (node.left  != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            res.add(temp);
        }

        return res;
    }
}

BM27 按之字形顺序打印二叉树(★★)

本质上是层次遍历

方法一:队列

public class Solution {
    public ArrayList<ArrayList<Integer>> Print (TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        if (pRoot == null) return res;
        ArrayDeque<TreeNode> queue = new ArrayDeque<TreeNode>();
        
        queue.offer(pRoot);
        while (!queue.isEmpty()) {
            int sz = queue.size(), t = res.size();
            ArrayList<Integer> temp = new ArrayList<Integer>();
            for (int i = 0; i < sz; i++) {
                TreeNode node = queue.poll();
                if (t % 2 == 0) {
                    temp.add(node.val);
                } else {
                    temp.add(0, node.val);
                }
                if (node.left  != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            res.add(temp);
        }

        return res;
    }
}

方法二:递归

public class Solution {
    ArrayList<ArrayList<Integer>> res;
    
    public ArrayList<ArrayList<Integer>> Print (TreeNode pRoot) {
        res = new ArrayList<ArrayList<Integer>>();
        helper(pRoot, 0);
        return res;
    }

    private void helper(TreeNode root, int deep) {
        if (root == null) return;
        if (res.size() <= deep) res.add(new ArrayList<Integer>());
        if (deep % 2 == 0) {
            res.get(deep).add(root.val);
        } else {
            res.get(deep).add(0, root.val);
        }
        helper(root.left, deep + 1);
        helper(root.right, deep + 1);
    }
}

BM28 二叉树的最大深度(★)

最大深度就是有多少层次

方法一:递归(50ms)

public class Solution {
    public int maxDepth (TreeNode root) {
        if (root == null) return 0;
        int lDepth = maxDepth(root.left);
        int rDepth = maxDepth(root.right);
        return 1 + Math.max(lDepth, rDepth);
    }
}

方法二:队列层次遍历

public class Solution {
    public int maxDepth (TreeNode root) {
        if (root == null) return 0;
        ArrayDeque<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.offer(root);
        int res = 0;
        while (!queue.isEmpty()) {
            int sz = queue.size();
            for (int i = 0; i < sz; i++) {
                TreeNode node = queue.poll();
                if (node.left != null)  queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            res += 1;
        }
        return res;
    }
}

BM29 二叉树中和为某一值的路径(一)(★)

public class Solution {
    public boolean hasPathSum (TreeNode root, int sum) {
        if (root == null) return false;
        if (root.left == null && root.right == null && root.val == sum) {
            return true;
        }
        boolean lHas = hasPathSum(root.left, sum - root.val);
        boolean rHas = hasPathSum(root.right, sum - root.val);
        return lHas || rHas;
    }
}

BM30 二叉搜索树与双向链表(★★)

方法一:中序遍历+递归(44ms)

public class Solution {
    TreeNode head, pre;

    public TreeNode Convert(TreeNode root) {
        if (root == null) return null;
        helper(root);
        return head;
    }

    private void helper(TreeNode cur) {
        if (cur == null) return;
        helper(cur.left);
        if (head == null) head = cur;
        if (pre == null) {
            pre = cur;
        } else {
            cur.left = pre;
            pre.right = cur;
            pre = cur;
        }
        helper(cur.right);
    }
}

方法二:中序遍历+链表封装(46ms)

public class Solution {
    ArrayList<TreeNode> list;
    public TreeNode Convert(TreeNode root) {
        if (root == null) return null;
        list = new ArrayList<TreeNode>();
        inorder(root);
        
        for (int i = 0; i < list.size() - 1; i++) {
            list.get(i).right = list.get(i + 1);
            list.get(i + 1).left = list.get(i);
        }
        return list.get(0);
    }

    private void inorder(TreeNode root) {
        if (root == null) return;
        inorder(root.left);
        list.add(root);
        inorder(root.right);
    }
}

BM31 对称的二叉树(★)

方法一:递归(29ms)

public class Solution {
    public boolean isSymmetrical (TreeNode pRoot) {
        return helper(pRoot, pRoot);
    }

    private boolean helper(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;
        boolean lb = helper(p.left, q.right);
        boolean rb = helper(p.right, q.left);
        return lb && rb;
    }
}

方法二:迭代+辅助栈(24ms)

public class Solution {
    public boolean isSymmetrical (TreeNode pRoot) {
        return helper(pRoot, pRoot);
    }

    private boolean helper(TreeNode p, TreeNode q) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(p);
        stack.push(q);
        while (!stack.isEmpty()) {
            TreeNode t1 = stack.pop();
            TreeNode t2 = stack.pop();
            if (t1 == null && t2 == null) continue;
            if (t1 == null || t2 == null || t1.val != t2.val) return false;
            
            stack.push(t1.left);
            stack.push(t2.right);

            stack.push(t1.right);
            stack.push(t2.left);
        }
        return true;
    }
}

BM32 合并二叉树(★)

方法一:new 新节点(24ms)

public class Solution {
    public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {
        if (t1 == null && t2 == null) return null;
        if (t1 == null) return t2;
        if (t2 == null) return t1;
        TreeNode node = new TreeNode(t1.val + t2.val);
        node.left  = mergeTrees(t1.left, t2.left);
        node.right = mergeTrees(t1.right, t2.right);
        return node;
    }
}

方法二:在树t1上面合并(24ms)

public class Solution {
    public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {
        if (t1 == null && t2 == null) return null;
        if (t1 == null) return t2;
        if (t2 == null) return t1;
        TreeNode node = t1;
        t1.val += t2.val;
        t1.left  = mergeTrees(t1.left, t2.left);
        t1.right = mergeTrees(t1.right, t2.right);
        return t1;
    }
}

BM33 二叉树的镜像(★)

方法一:递归+O(N)空间复杂度(33ms)

public class Solution {
    public TreeNode Mirror (TreeNode root) {
        if (root == null) return null;
        TreeNode node = new TreeNode(root.val);
        node.left = Mirror(root.right);
        node.right = Mirror(root.left);
        return node;
    }
}

方法二:递归+O(1)空间复杂度(33ms)

public class Solution {
    public TreeNode Mirror (TreeNode root) {
        if (root == null) return null;
        TreeNode lnode = Mirror(root.left);
        TreeNode rnode = Mirror(root.right);
        root.left  = rnode;
        root.right = lnode;
        return root;
    }
}

BM34 判断是不是二叉搜索树(★★)

方法一:递归(161ms)

public class Solution {
    TreeNode pre;
    public boolean isValidBST (TreeNode root) {
        if (root == null) return true;
        boolean lb = isValidBST(root.left);
        if (pre != null && pre.val > root.val) return false;
        pre = root;
        boolean rb = isValidBST(root.right);
        return lb && rb;
    }
}

BM35 判断是不是完全二叉树(★★)

方法一:层次遍历

public class Solution {
    public boolean isCompleteTree (TreeNode root) {
        if (root == null) return true;
        boolean isNull = true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node == null) {
                isNull = false;
            } else {
                if (isNull == false) return false;
                queue.offer(node.left);
                queue.offer(node.right);
            }
        }

        return true;
    }
}

BM36 判断是不是平衡二叉树(★)

public class Solution {
    public boolean IsBalanced_Solution (TreeNode pRoot) {
        int v = helper(pRoot);
        return v >= 0;
    }

    private int helper(TreeNode root) {
        if (root == null) return 0;
        int lb = helper(root.left);
        int rb = helper(root.right);
        if (lb >= 0 && rb >= 0 && Math.abs(lb - rb) <= 1) {
            return 1 + Math.max(lb, rb);
        } else {
            return -1;
        }
    }
}

BM37 二叉搜索树的最近公共祖先(★)

分类讨论即可

public class Solution {
    public int lowestCommonAncestor (TreeNode root, int p, int q) {
        if (p < root.val && q < root.val) {
            return lowestCommonAncestor(root.left, p, q);
        } else if (p > root.val && q > root.val) {
            return lowestCommonAncestor(root.right, p, q);
        } else {
            return root.val;
        }
    }
}

BM38 在二叉树中找到两个节点的最近公共祖先(★★)

方法一:递归

分类讨论

public class Solution {
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        if (root == null) return 0;
        if (root.val == o1 || root.val == o2) return root.val;
        int lv = lowestCommonAncestor(root.left, o1, o2);
        int rv = lowestCommonAncestor(root.right, o1, o2);
        if (lv != 0 && rv != 0) return root.val;
        return lv == 0 ? rv : lv;
    }
}

BM39 序列化二叉树(★★★)

层序遍历

public class Solution {
    String Serialize(TreeNode root) {
        if (root == null) return "";

        StringBuffer sr = new StringBuffer();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        sr.append(root.val);

        while (!queue.isEmpty()) {
            sr.append(",");
            TreeNode node = queue.poll();
            if (node.left != null) {
                queue.offer(node.left);
                sr.append(node.left.val);
            } else {
                sr.append("n");
            }
            sr.append(",");
            if (node.right != null) {
                queue.offer(node.right);
                sr.append(node.right.val);
            } else {
                sr.append("n");
            }
        }

        return sr.toString();
    }

    TreeNode Deserialize(String str) {
        if (str.equals("")) return null;

        String[] vals = str.split(",");
        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode root = new TreeNode(Integer.valueOf(vals[0]));
        queue.offer(root);
        int k = 1;

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (!vals[k].equals("n")) {
                TreeNode lnode = new TreeNode(Integer.valueOf(vals[k]));
                node.left = lnode;
                queue.offer(lnode);
            }
            k++;
            if (!vals[k].equals("n")) {
                TreeNode rnode = new TreeNode(Integer.valueOf(vals[k]));
                node.right = rnode;
                queue.offer(rnode);
            }
            k++;
        }

        return root;
    }
}

BM40 重建二叉树(★★)

方法一:dfs

public class Solution {
    public TreeNode reConstructBinaryTree (int[] preOrder, int[] inOrder) {
        return helper(preOrder, inOrder, 0, 0, inOrder.length - 1);
    }

    private TreeNode helper(int[] preOrder, int[] inOrder, int cur, int le, int ri) {
        if (le > ri)  return null;
        TreeNode node = new TreeNode(preOrder[cur]);
        int mid = le;
        while (mid <= ri && inOrder[mid] != node.val) mid++;
        node.left  = helper(preOrder, inOrder, cur + 1, le, mid - 1);
        node.right = helper(preOrder, inOrder, cur + mid - le + 1, mid + 1, ri);
        return node;
    }
}

BM41 输出二叉树的右视图(★★)

方法:先构建二叉树,然后层序遍历(18ms)

public class Solution {
    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int val) {
            this.val = val;
        }
    }

    public int[] solve (int[] preOrder, int[] inOrder) {
        TreeNode root = buildTree(preOrder, inOrder, 0, 0, preOrder.length - 1);
        int[] res  = leftView(root);
        return res;
    }

    private TreeNode buildTree(int[] preOrder, int[] inOrder, int cur, int le, int ri) {
        if (le > ri) return null;
        TreeNode node = new TreeNode(preOrder[cur]);
        int mid = le;
        while (mid < ri && inOrder[mid] != node.val) mid++;
        node.left  = buildTree(preOrder, inOrder, cur + 1, le, mid - 1);
        node.right = buildTree(preOrder, inOrder, cur + mid - le + 1, mid + 1, ri);
        return node; 
    }

    private int[] leftView(TreeNode root) {
        if (root == null) return new int[]{};
        List<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while(!queue.isEmpty()) {
            int sz = queue.size();
            for (int i = 0; i < sz; i++) {
                TreeNode node = queue.poll();
                if (i + 1 == sz) list.add(node.val);
                if (node.left != null)  queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
        }

        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) res[i] = list.get(i);
        return res;
    }

}

你可能感兴趣的:(LeetCode,二叉树,算法,数据结构,面试)