83 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

二叉树

前序遍历

顺序是遍历根节点, 左子树, 右子树

    class TreeNode {

        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        TreeNode() {
        }

        TreeNode(int val) {
            this.val = val;
        }

    }

    /**
     * 递归前序遍历 时间复杂度O(N) 空间复杂度O(H)
     */
    public void preOrder(TreeNode root, List<Integer> ans) {
        if (root != null) {
            ans.add(root.val);
            preOrder(root.left, ans);
            preOrder(root.right, ans);
        }
    }

    /**
     * 栈的前序遍历 时间复杂度O(N) 空间复杂度O(H)
     */
    public List<Integer> preOrderTraversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> ans = new ArrayList<>();
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                ans.add(root.val);
                root = root.left;
            }
            root = stack.peek();
            stack.pop();
            root = root.right;
        }
        return ans;

    }

二叉搜索树

题目: 给定一棵二叉树,判断是否是二叉搜索树。

    private boolean f;

    public boolean isValidBST(TreeNode root) {
        f = true;
        preOrder(root, Long.MIN_VALUE, Long.MAX_VALUE);
        return f;
    }

    private void preOrder(TreeNode root, Long min, Long max) {
        if (root == null || !f) {
            return;
        }

        if (!(min < root.val && max > root.val)) {
            f = false;
            return;
        }

        preOrder(root.left, min, Long.valueOf(root.val));
        preOrder(root.right, Long.valueOf(root.val), max);
    }

目标和的所有路径

题目: 给定一棵二叉树, 一个目标值,输出所有路径,需要满足根节点到叶子节点之和等于给定的目标值

输入:target = 9

输出:[[5,4], [5,3,1]]

 private List<List<Integer>> ans = new ArrayList<>();

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<Integer> path = new ArrayList<>();
        backtrace(root, path, 0, sum);
        return ans;
    }

    private void backtrace(TreeNode root, List<Integer> path, int sum, int target) {
        if (root == null) {
            return;
        }

        sum += root.val;

        path.add(root.val);

        if(root.left == null && root.right == null){
            if(sum == target){
                ans.add(new ArrayList<>(path));
            }
        } else {
            backtrace(root.left, path, sum, target);
            backtrace(root.right, path, sum, target);
        }
        path.remove(path.size()-1);
    }

中序遍历

遍历从左子树,根节点,右子树开始遍历

    public List<Integer> inorderTraversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> result = new ArrayList<>();

        if(root != null || !stack.empty()){
            while(root != null){
                stack.push(root);
                root = root.left;
            }

            root = stack.peek();
            stack.pop();
            result.add(root.val);

            root = root.right;

        }
        return result;
    }

二叉搜索树

    private boolean bst;
    private Long preValue;
    public boolean isValidBSTMid(TreeNode root) {
        bst = true;
        preValue = Long.MIN_VALUE;
        midOrder(root);
        return bst;
    }


    private void midOrder(TreeNode root) {
        if(!bst){
            return;
        }

        if(root != null){
            midOrder(root.left);
            if(preValue >= root.val){
                bst = false;
                return;
            }

            preValue = Long.valueOf(root.val);
            midOrder(root.right);
        }
    }

删除二叉搜索数的节点

题目: 删除二叉搜索树的指定结点。返回删除之后的根结点。

private void swapValue(TreeNode a, TreeNode b){
        int t = a.val;
        a.val = b.val;
        b.val = t;
    }

    public TreeNode deleteNode(TreeNode root, int key){
        if(root == null ){
            return null;
        }

        if(key < root.val){
            root.left = deleteNode(root.left, key);
        } else if(key > root.val){
            root.right = deleteNode(root.right, key);
        }else {
            if(root.left == null && root.right == null){
                return null;
            } else if(root.left != null){
                TreeNode large = root.left;
                while(large.right != null){
                    large = large.right;
                }
                swapValue(root, large);
                root.left = deleteNode(root.left, key);
            } else if(root.right != null){
                TreeNode small = root.right;
                while(small.left != null){
                    small = small.left;
                }
                swapValue(root, small);
                root.right = deleteNode(root.right, key);
            }
        }
        return root;
    }

后序处理

左子树 右子树 根节点

    private void preOrderAfter(TreeNode root, List<Integer> result) {
        if (root != null) {
            preOrderAfter(root.left, result);
            preOrderAfter(root.right, result);
            result.add(root.val);
        }
    }
 public List<Integer> postorderTraversal(TreeNode root){
        List<Integer> resultList = new ArrayList<>();
        TreeNode pre = null;
        Stack<TreeNode> stack = new Stack<>();

        while(!stack.isEmpty() || root != null){
            while(root != null){
                stack.push(root);
                root = root.left;
            }

            root = stack.peek();
            if(root.right == null || root.right == pre){
                resultList.add(root.val);
                stack.pop();
                pre = root;
                root = null;
            } else {
                root = root.right;
            }
        }
        return resultList;
    }

最低公共祖先

TreeNode res = null;

    private int postOrder(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return 0;
        }

        int lcnt = postOrder(root.left, p, q);
        int rcnt = postOrder(root.right, p, q);
        if(lcnt ==1 && rcnt ==1){
            res = root;
        } else if(lcnt ==1 || rcnt ==1) {
            if(root ==p || root==q){
                res = root;
            }
        }
        return lcnt + rcnt + ((root==p||root==q)? 1:0);
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p , TreeNode q){
        postOrder(root, p, q);
        return res;
    }