【代码随想录】-二叉树专题

理论基础

二叉树是天然的递归结构!

求深度选用前序遍历,求高度选用后序遍历。深度从上至下1 2 3 高度从下至上1 2 3

遍历二叉树

递归遍历

/**
     * 递归,先序遍历 leetcode-144
     *
     * @param root
     * @return
     */
public List<Integer> preorderTraversal(TreeNode root) {
    if (root == null) return new ArrayList<>();
    list.add(root.val);
    preorderTraversal(root.left);
    preorderTraversal(root.right);
    return list;
}

/**
     * 递归:中序遍历 leetcode-94
     *
     * @param root
     * @return
     */
public List<Integer> inorderTraversal(TreeNode root) {
    if (root == null) return new ArrayList<>();
    inorderTraversal(root.left);
    list.add(root.val);
    inorderTraversal(root.right);
    return list;
}

/**
     * 后序遍历  leetcode-145
     *
     * @param root
     * @return
     */
public List<Integer> postorderTraversal(TreeNode root) {
    if (root == null) return new ArrayList<>();
    postorderTraversal(root.left);
    postorderTraversal(root.right);
    list.add(root.val);
    return list;
}

迭代遍历

/**
     * 迭代,先序遍历 leetcode-144
     *
     * @param root
     * @return
     */
public  List<Integer> preorderTraversal2(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    if(root == null) return list;
    //用栈来实现  先入右节点 后入左节点
    Deque<TreeNode> stack = new LinkedList<>();
    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);
    }
    return list;
}

/**
     * 迭代:中序遍历 leetcode-94
     *
     * @param root
     * @return
     */
public static List<Integer> inorderTraversal2(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    if(root == null) return list;
    Deque<TreeNode> stack = new LinkedList<>();
    TreeNode p = root;
    while (!stack.isEmpty() || p!= null) {
        //有左入左,没左出栈,入右
        while(p != null){
            stack.push(p);
            p = p.left;
        }
        p = stack.pop();
        list.add(p.val);
        p = p.right;
    }
    return list;
}

/**
     * 迭代,后序遍历  leetcode-145
     *
     * @param root
     * @return
     */
public static List<Integer> postorderTraversal2(TreeNode root) {
    //后序遍历是左右根 先序遍历是根左右,将其变成根右左,再反转即可得到后序
    List<Integer> list = new ArrayList<>();
    if(root == null) return list;
    Deque<TreeNode> stack = new LinkedList<>();
    Deque<TreeNode> res = new LinkedList<>();
    stack.push(root);
    while (!stack.isEmpty()){
        TreeNode node = stack.pop();
        res.push(node);
        if(node.left != null) stack.push(node.left);
        if(node.right != null) stack.push(node.right);
    }
    while (!res.isEmpty()){
        list.add(res.pop().val);
    }
    return list;
}

层次遍历

/**
     * 层次遍历
     *
     * @param root
     * @return
     */
public List<List<Integer>> levelOrder(TreeNode root) {
    //用队列实现
    List<List<Integer>> res = new ArrayList<>();
    Queue<TreeNode> queue = new LinkedList<>();
    if (root == null) return res;
    queue.offer(root);
    while (!queue.isEmpty()) {
        List<Integer> list = new ArrayList<>();
        int len = queue.size();
        while (len > 0) {
            TreeNode node = queue.poll();
            list.add(node.val);
            if (node.left != null) queue.offer(node.left);
            if (node.right != null) queue.offer(node.right);
            len--;
        }
        res.add(list);
    }
    return res;
}

翻转二叉树

/**
     * 反转二叉树leetcode-226
     * @param root
     * @return
     */
public TreeNode invertTree(TreeNode root) {
    //把每个节点的左右子树交换即可
    //使用先序遍历 后序和层次遍历均可  中序比较麻烦 有些节点会重复交换
    if(root == null) return root;
    TreeNode temp = root.left;
    root.left = root.right;
    root.right = temp;
    invertTree(root.left);
    invertTree(root.right);
    return root;
}

对称二叉树

迭代:

/**
     * 迭代法,leetcode-101
     *
     * @param root
     * @return
     */
public boolean isSymmetric(TreeNode root) {
    //迭代法中只需要把左右子树要比较的节点按顺序加入容器,然后成对地拿出来比较
    //用栈、队列、甚至数组均可
    //java中双端队列更方便操作
    Deque<TreeNode> deque = new LinkedList<>();
    if (root == null) return true;
    deque.offerFirst(root.left);
    deque.offerLast(root.right);
    while (!deque.isEmpty()) {
        TreeNode leftNode = deque.pollFirst();
        TreeNode rightNode = deque.pollLast();
        if (leftNode == null && rightNode == null) continue;
        if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
            return false;
        }
        deque.offerFirst(leftNode.left);
        deque.offerFirst(leftNode.right);
        deque.offerLast(rightNode.right);
        deque.offerLast(rightNode.left);
    }
    return true;
}

递归:

/**
     * 递归,leetcode-101
     *
     * @param root
     * @return
     */
public boolean isSymmetric2(TreeNode root) {
    if (root == null) return true;
    return compare(root.left, root.right);
}

public boolean compare(TreeNode leftNode, TreeNode rightNode) {
    if (leftNode == null && rightNode == null) return true;
    if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) { //有一个空就false
        return false;
    }
    boolean out = compare(leftNode.left, rightNode.right); //外侧是否相等
    boolean in = compare(leftNode.right, rightNode.left);//内测是否相等
    return out && in; //同时相等才为真
}

类似题目

/**
     *相同的树 leetcode-100
     * @param p
     * @param q
     * @return
     */
public boolean isSameTree(TreeNode p, TreeNode q) {
    if(p == null && q == null) return true;
    if(p == null || q ==null || p.val!=q.val){
        return false;
    }
    boolean left = isSameTree(p.left, q.left);
    boolean right = isSameTree(p.right,q.right);
    return left&&right;
}
/**
     * 判断子树 leetcode-572
     * @param root
     * @param subRoot
     * @return
     */
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    if (root == null && subRoot == null) return true;
    if (root == null || subRoot == null ) { //有一个空就false
        return false;
    }
    boolean res1 = isSameTree(root,subRoot);
    boolean res2 = isSubtree(root.left,subRoot);
    boolean res3 = isSubtree(root.right,subRoot);
    return res1 || res2 || res3;
}

public boolean isSameTree(TreeNode p, TreeNode q) {
    if(p == null && q == null) return true;
    if(p == null || q ==null || p.val!=q.val){
        return false;
    }
    boolean left = isSameTree(p.left, q.left);
    boolean right = isSameTree(p.right,q.right);
    return left&&right;
}

二叉树最大深度

要注意高度与深度的区别:高度是以最下面叶子节点为水平面,深度是以根节点为水平面

/**
     * 递归法-1,二叉树的最大深度 leetcode -104
     * @param root
     * @return
     */
int max = 0;
public int maxDepth(TreeNode root) {
    getDepth(root,0);
    return max;
}

public void getDepth(TreeNode root,int depth){
    if(root == null) return;
    depth++;
    max = Math.max(max,depth);//保存最大的深度
    getDepth(root.left,depth);
    getDepth(root.right,depth);
}

/**
     * 递归法-2,二叉树的最大深度 leetcode -104
     * @param root
     * @return
     */
public int maxDepth2(TreeNode root){
    if(root == null) return 0;
    int depth1 = maxDepth2(root.left);
    int depth2 = maxDepth2(root.right);
    return Math.max(depth1,depth2)+1;
}

/**
     * 迭代法,二叉树的最大深度 leetcode -104
     * @param root
     * @return
     */
public int maxDepth3(TreeNode root){
    //使用层次遍历
    int depth = 0;
    if(root == null) return depth;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    while (!deque.isEmpty()){
        depth++;
        int size = deque.size();
        while (size > 0){
            TreeNode node = deque.poll();
            if(node.left!=null) deque.offer(node.left);
            if(node.right!=null) deque.offer(node.right);
            size--;
        }
    }
    return depth;
}

二叉树最小深度

/**
     * 二叉树的最小深度 leetcode-111
     *
     * @param root
     * @return
     */
public int minDepth(TreeNode root) {
    // 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
    if (root == null) return 0;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    int high = 0;
    while (!deque.isEmpty()) {
        int size = deque.size();
        high++;
        while (size > 0) {
            TreeNode node = deque.poll();
            if (node.left == null && node.right == null) {
                return high;
            }
            if (node.left != null) deque.offer(node.left);
            if (node.right != null) deque.offer(node.right);
            size--;
        }
    }
    return high;
}

/**
     * 递归法
     *
     * @param root
     * @return
     */
public int minDepth2(TreeNode root) {
    //与求最大深度不一样的地方在于 左右孩子有一个为空的情况
    if (root == null) return 0;
    //左右孩子有一个为空 返回高的
    if (root.left == null && root.right != null) return 1 + minDepth2(root.right);
    if (root.right == null && root.left != null) return 1 + minDepth2(root.left);
    int high1 = minDepth2(root.left);
    int high2 = minDepth2(root.right);
    return Math.min(high1, high2) + 1;

}

完全二叉树的节点个数

/**
     * 迭代,222. 完全二叉树的节点个数
     *
     * @param root
     * @return
     */
public int countNodes(TreeNode root) {
    if (root == null) return 0;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    int res = 0;
    while (!deque.isEmpty()) {
        int size = deque.size();
        res += size;
        while (size > 0) {
            TreeNode node = deque.poll();
            if (node.left != null) deque.offer(node.left);
            if (node.right != null) deque.offer(node.right);
            size--;
        }
    }
    return res;
}

/**
     * 递归-1,222. 完全二叉树的节点个数
     *
     * @param root
     * @return
     */
public int countNodes2(TreeNode root) {
    if (root == null) return 0;
    List<Integer> list = new ArrayList<>();
    count(root, list);
    return list.size();
}

public void count(TreeNode root, List<Integer> list) {
    if (root == null) return;
    list.add(root.val);
    count(root.left, list);
    count(root.right, list);
}

/**
     * 递归-2,222. 完全二叉树的节点个数
     *
     * @param root
     * @return
     */
public int countNodes3(TreeNode root) {
    if (root == null) return 0;
    int left = countNodes3(root.left);
    int right = countNodes3(root.right);
    return left + right + 1;
}

判断是否是平衡二叉树

/**
     * 判断是否是平衡二叉树 leetcode-110
     *
     * @param root
     * @return
     */
public boolean isBalanced(TreeNode root) {
    //获取高度 用后序遍历
    return getHeight(root) != -1;
}

public int getHeight(TreeNode root) {
    if (root == null) return 0;
    int left = getHeight(root.left); 
    if (left == -1) return -1; //一旦不平衡就返回 递归终止条件 
    //可以想想根节点的左子树是1 2 3 4 右子树也是1 2 3 4 整个树形状是“^” 显然不平衡 左边不平衡了就直接返回 若不返回 最后得到的结果是平衡
    int right = getHeight(root.right);
    if (right == -1) return -1;
    if (Math.abs(left - right) > 1) { //不平衡
        return -1;
    } else {
        return Math.max(left, right) + 1;
    }
}

// 方法2
boolean res = true;
public boolean isBalanced(TreeNode root) {
    height(root);
    return res;
}

public int height(TreeNode root){
    if(root == null) return 0;
    int left = height(root.left);
    int right = height(root.right);
    if(Math.abs(left-right) > 1){
        res = false;
    }
    return Math.max(left,right)+1;

}

二叉树的所有路径

String虽然是引用类型,每次+或者赋值其实都是生成了一个新的String对象,即在递归过程中也不存在分支污染问题,不需要回溯操作

/**
     * 递归,返回二叉树的所有路径
     * @param root
     * @return
     */
public List<String> binaryTreePaths(TreeNode root) {
    List<String> list = new ArrayList<>();
    if(root == null ) return list;
    getPaths(root,list,"");
    return list;
}

public void getPaths(TreeNode root,List<String> list,String path){
    if(root == null) return;
    if(root.left == null && root.right == null) {
        list.add( path+root.val);
        return;
    }
    //非叶子节点  遍历它的左右节点
    getPaths(root.left,list,path + root.val + "->");
    getPaths(root.right,list,path + root.val + "->");
}

/**
     * 广度优先
     * @param root
     * @return
     */
public List<String> binaryTreePaths2(TreeNode root) {
    if(root == null) return new ArrayList<>();
    List<String> list = new ArrayList<>();
    Deque<Object> deque = new LinkedList<>();
    deque.offer(root);
    deque.offer(root.val + "");
    while (!deque.isEmpty()){
        TreeNode node = (TreeNode) deque.poll();
        String path = (String) deque.poll(); //成对加入
        if(node.left == null && node.right == null){
            list.add(path);
        }
        if(node.left != null){
            deque.offer(node.left);;
            deque.offer(path+"->"+node.left.val);
        }
        if(node.right != null){
            deque.offer(node.right);
            deque.offer(path+"->"+node.right.val);
        }
    }
    return list;
}

左叶子节点之和

/**
     * 迭代法,左叶子之和 leetcode-404
     * @param root
     * @return
     */
public int sumOfLeftLeaves(TreeNode root) {
    int sum = 0;
    if(root == null) return sum;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    while (!deque.isEmpty()){
        TreeNode node = deque.poll();
        if(node.left != null){
            deque.offer(node.left);
            if(node.left.left == null && node.left.right == null) sum+=node.left.val;
        }
        if(node.right != null){
            deque.offer(node.right);
        }
    }
    return sum;
}

/**
     * 递归,左叶子之和 leetcode-404
     * @param root
     * @return
     */
int res = 0;
public int sumOfLeftLeaves2(TreeNode root) {

    if(root == null) return 0;
    if(root.left != null && root.left.left == null && root.left.right == null){
        res += root.left.val;
    }
    sumOfLeftLeaves2(root.left);
    sumOfLeftLeaves2(root.right);
    return res;
}

public int sumOfLeftLeaves3(TreeNode root) {

    int leftVal = sumOfLeftLeaves(root.left);  //递归左子树,返回左子树左叶子的值
    int rightVal = sumOfLeftLeaves(root.right);    //递归右子树,返回右子树左叶子的值
    int curLeftVal = 0; //中
    if(root.left != null && root.left.left == null && root.left.right == null){
        curLeftVal = root.left.val; //左叶子的值
    }
    return curLeftVal + leftVal + rightVal; //左+右+根 可以联系求深度来理解
}

找树左下角的值

/**
     * leetcode-513 找树左下角的值
     *
     * @param root
     * @return
     */
public int findBottomLeftValue(TreeNode root) {
    if (root == null) return 0;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    int res = 0;
    while (!deque.isEmpty()) {
        int size = deque.size();
        res = deque.peek().val;
        while (size > 0) {
            TreeNode node = deque.poll();
            if (node.left != null) deque.offer(node.left);
            if (node.right != null) deque.offer(node.right);
            size--;
        }
    }
    return res;
}

/**
     * leetcode-513 找树左下角的值
     *
     * @param root
     * @return
     */
int max = 0; int res;
public int findBottomLeftValue2(TreeNode root) {
    if (root == null) return 0;
    //最后一行最左边
    dfs(root,1);
    return res;
}

void dfs(TreeNode root,int depth){
    if(root == null)return;
    if(depth > max) {
        max = depth;
        res = root.val;
    }
    dfs(root.left,depth+1);
    dfs(root.right,depth+1);
}

路径总和

/**
     * leetcode-112 路径总和
     * @param root
     * @param targetSum
     * @return
     */
public boolean hasPathSum(TreeNode root, int targetSum) {
    if(root == null) return false;
    int sum = 0;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    while (!deque.isEmpty()){
        TreeNode node = deque.poll();
        if(node.left == null && node.right == null && node.val == targetSum) return true;
        if(node.left != null) {
            deque.offer(node.left);
            node.left.val += node.val;
        }
        if(node.right != null) {
            deque.offer(node.right);
            node.right.val+=node.val;
        }
    }
    return false;
}


/**
     * leetcode-112 路径总和
     * @param root
     * @param targetSum
     * @return
     */
public boolean hasPathSum2(TreeNode root, int targetSum) {
    if(root == null) return false;
    if(root.left == null && root.right == null && root.val == targetSum) return true;
    boolean flag = hasPathSum(root.left,targetSum-root.val);
    boolean flag2 = hasPathSum(root.right,targetSum-root.val);
    return flag || flag2;
}

路径总和2

/**-
     * 路径总和2 leetcode -113
     * @param root
     * @param targetSum
     * @return
     */
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
    List<List<Integer>> list = new ArrayList<>();
    if(root == null) return list;
    Deque<TreeNode> dequeNode = new LinkedList<>();
    Deque<List<Integer>> dequeList = new LinkedList<>();
    List<Integer> subList = new ArrayList<>();
    subList.add(root.val);
    dequeNode.offer(root);
    dequeList.offer(subList);
    while (!dequeNode.isEmpty()){
        TreeNode node = dequeNode.poll();
        List<Integer> tempList = dequeList.poll();
        if(node.left == null && node.right == null && node.val == targetSum) {
            list.add(tempList);
        }
        if(node.left != null) {
            tempList.add(node.left.val);
            dequeNode.offer(node.left);
            //list是引用传递 进行修改会影响其他list的值
            dequeList.add(new ArrayList<>(tempList));
            node.left.val += node.val;
            tempList.remove(tempList.size()-1);
        }
        if(node.right != null) {
            dequeNode.offer(node.right);
            tempList.add(node.right.val);
            dequeList.add(new ArrayList<>(tempList));
            node.right.val+=node.val;

        }
    }
    return list;
}

public List<List<Integer>> pathSum2(TreeNode root, int sum) {
    List<List<Integer>> result = new ArrayList<>();
    dfs(root, sum, new ArrayList<>(), result);
    return result;
}

public void dfs(TreeNode root, int sum, List<Integer> list,
                List<List<Integer>> result) {
    if(root == null) return;
    ArrayList<Integer> subList = new ArrayList<>(list);
    subList.add(root.val);
    if(root.left == null && root.right == null && root.val == sum){
        result.add(subList);
    }
    dfs(root.left,sum-root.val,subList,result);
    dfs(root.right,sum-root.val,subList,result);
}

中序和后序构造二叉树

//leetcode-106
Map<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
    for (int i = 0; i < inorder.length; i++) {
        map.put(inorder[i],i);
    }
    return buildTree2(postorder,0,inorder.length-1,0,postorder.length-1);
}

public TreeNode buildTree2(int[] postorder,int lIn,int rIn,
                           int lPost,int rPost) {
    if(lIn > rIn || lPost > rPost) return null;
    int rootVal = postorder[rPost]; //根节点的值
    TreeNode root = new TreeNode(rootVal);
    //在中序遍历中找到根
    int index =map.get(rootVal);
    //        中序数组大小一定是和后序数组的大小相同的
    root.left = buildTree2(postorder,lIn,index-1,lPost,lPost+index-lIn-1);
    root.right = buildTree2(postorder,index+1,rIn,lPost+index-lIn,rPost-1);
    return root;
}

最大二叉树

//leetcode-654
public TreeNode constructMaximumBinaryTree(int[] nums) {
    return buildTree(0,nums.length-1,nums);
}

public TreeNode buildTree(int start,int end ,int[] nums){
    if(end < start) return null;
    int maxIndex = getMaxIndex(start, end, nums);
    TreeNode root = new TreeNode(nums[maxIndex]);
    root.left = buildTree(start,maxIndex-1,nums);
    root.right = buildTree(maxIndex+1,end,nums);
    return root;
}

public int getMaxIndex(int start,int end ,int[] nums){
    int max = nums[start];
    int maxIndex = start;
    for (int i = start; i <= end; i++) {
        if(nums[i] > max){
            max = nums[i];
            maxIndex = i;
        }
    }
    return maxIndex;
}

合并二叉树

/**
     * leetcode-617
     * @param root1
     * @param root2
     * @return
     */
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
    if(root1 == null) return root2;
    if(root2 == null) return root1;
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root1);
    deque.offer(root2);
    while (!deque.isEmpty() ){
        TreeNode node1 = deque.poll();
        TreeNode node2 = deque.poll();
        node1.val+=node2.val;
        if(node1.left != null && node2.left!= null){
            deque.offer(node1.left);
            deque.offer(node2.left);
        } else if (node1.left == null) { // 树1 的左子树为空 直接把树2 的左子树拿过来挂着
            node1.left = node2.left;
        }

        if(node1.right != null && node2.right!= null){
            deque.offer(node1.right);
            deque.offer(node2.right);
        } else if (node1.right == null) {
            node1.right = node2.right;
        }
    }
    return root1;
}

/**
     * 递归
     * @param root1
     * @param root2
     * @return
     */
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if(root1 == null) return root2;
        if(root2 == null) return root1;
        root1.val+=root2.val;
        root1.left = mergeTrees(root1.left,root2.left);
        root1.right = mergeTrees(root1.right,root2.right);
        return root1;
    }   
}

二叉搜索树中的搜索


/**
     * leetcode-700. 二叉搜索树中的搜索
     * @param root
     * @param val
     * @return
     */
public TreeNode searchBST(TreeNode root, int val) {
    if(root == null) return root;
    if(val > root.val ){
        return searchBST(root.right,val); //搜索到了结果就要返回 不然返回值没了
    }else if(val < root.val){
        return searchBST(root.left,val);
    }else{
        return root;
    }
}

public TreeNode searchBST2(TreeNode root, int val) {
    if(root == null) return root;
    while (root != null && root.val != val){
        if(val > root.val ) root = root.right;
        else {
            root  = root.left;
        }
    }
    return root;
}

是否是二叉搜索树

/**
     * 验证是否是二叉搜索树 leetcode-98
     *
     * @param root
     * @return
     */
long max = Long.MIN_VALUE;

public boolean isValidBST(TreeNode root) {
    //二叉排序树的后序是有序序列
    if (root == null) return true;
    // 不能像这样单纯的比较 因为左子树的所有节点均小于根节点 ……
    //       if(root.left.val < root.val && root.right.val > root.val){
    //           return true;
    //       }

    boolean left = isValidBST(root.left);
    if (root.val > max) max = root.val;
    else return false;
    boolean right = isValidBST(root.right);
    return left && right;
}

//方法2
TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
    if(root == null) return true;
    boolean left = isValidBST(root.left);
    if(pre != null && root.val <= pre.val) return false;
    pre = root;
    boolean right = isValidBST(root.right);
    return left&&right;
}

二叉搜索树的最小绝对误差

/**
     * leetcode-530. 二叉搜索树的最小绝对差
     * @param root
     * @return
     */
int min = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
    if(root ==null) return 0;
    inOrder(root);
    return min;
}

TreeNode pre = null;
public void inOrder(TreeNode root){
    if (root == null) return ;
    inOrder(root.left);
    if(pre != null)
        min = Math.min(root.val-pre.val,min);
    pre = root;
    inOrder(root.right);
}

二叉搜索树中的众数

/**
     * 501. 二叉搜索树中的众数
     * @param root
     * @return
     */
TreeNode pre = null;
List<Integer> list = new ArrayList<>();
int count = 0;
int maxCount = 0; //记录最大值
public int[] findMode(TreeNode root) {
    if(root == null) return new int[]{};
    inOrder(root);
    int[] res = new int[list.size()];
    for (int i = 0; i < list.size(); i++) {
        res[i] = list.get(i);
    }
    return res;
}


public void inOrder(TreeNode root){
    if(root == null) return;
    inOrder(root.left);
    if(pre == null || pre.val != root.val){
        count=1;
    }else count++;
    if(count > maxCount){ //有更大频率的就清空list 并将当前最大添加到list
        list.clear();
        maxCount = count;
        list.add(root.val);
    }else if(count == maxCount){
        list.add(root.val);
    }
    pre = root;
    inOrder(root.right);
}

二叉树的最近公共祖先

/**
     * 236. 二叉树的最近公共祖先
     * @param root
     * @param p
     * @param q
     * @return
     */
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    // 如果 root == q,或者 root == p,说明找到 q p ,则将其返回
        if(root == null || p == root || q == root) return root;
        //后序
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right  = lowestCommonAncestor(root.right,p,q);
        //如果 左右子树的返回值都不为空,说明此时的根节点,一定是q 和p 的最近祖先。
        //另一种情况 根节点5 它的左子树3 找它们的最近公共祖先  此类情况已被上面方案包含
        if(root.left != null && root.right != null) return root;
        if(root.left != null)return left; //哪个不为空就往上返回
        else {
            return right;
        }
}

二叉搜索树的最近公共祖先

/**
     *  递归  leetcode-235 二叉搜索树的最近公共祖先
     * @param root
     * @param p
     * @param q
     * @return
     */
public TreeNode lowestCommonAncestor4(TreeNode root, TreeNode p, TreeNode q) {
    if(p.val < root.val && q.val < root.val){
        return lowestCommonAncestor(root.left,p,q); //搜索到了结果就要返回
    }else if(p.val > root.val && q.val > root.val){
        return lowestCommonAncestor(root.right,p,q);
    }
    return root;
}



/**
     * leetcode-235 二叉搜索树的最近公共祖先
     * @param root
     * @param p
     * @param q
     * @return
     */
TreeNode res = null;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    //深度遍历  若遍历的当前节点的值介于p和q之间则可以直接返回  因为是二叉搜索树
    // p和q不一定谁大
    if(p.val < q.val)  dfs(root,p,q);
    else  dfs(root,q,p);
    return res;
}

public void  dfs(TreeNode root,TreeNode p, TreeNode q){
    if(root == null) return;
    if(p.val <= root.val && root.val <= q.val){
        res = root;
        return;
    }
    dfs(root.left,p,q);
    dfs(root.right,p,q);
}

/**
     *  迭代  leetcode-235 二叉搜索树的最近公共祖先
     * @param root
     * @param p
     * @param q
     * @return
     */
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
    while (root != null){
        if(root.val > p.val && root.val > q.val){
            root = root.left;
        } else if (root.val < p.val && root.val < q.val) {
            root = root.right;
        }else{
            return root;
        }
    }
    return root;
}

二叉搜索树中的插入操作

/**
     * leetcode-701 二叉搜索树中的插入
     * @param root
     * @param val
     * @return
     */
public TreeNode insertIntoBST(TreeNode root, int val) {
    if(root == null) return new TreeNode(val);
    TreeNode res = root;
    while (true){
        if(val >root.val){
            if(root.right != null) root = root.right;
            else {
                root.right = new TreeNode(val);
                break;
            }
        }else {
            if(root.left != null) root = root.left;
            else {
                root.left = new TreeNode(val);
                break;
            }
        }
    }
    return res;
}
//递归
public TreeNode insertIntoBST(TreeNode root, int val) {
    //        终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。
    if(root == null){
        TreeNode node = new TreeNode(val);
        return node; //这里把添加的节点返回给上一层,就完成了父子节点的赋值操作了
    }
    //        下一层将加入节点返回,本层用root->left或者root->right将其接住。
    if(root.val > val) root.left = insertIntoBST(root.left,val);
    if(root.val < val) root.right = insertIntoBST(root.right,val);
    return root;
}

删除二叉搜索树中的节点

/**
     * leetcode-450 删除二叉搜索树中的节点
     * @param root
     * @param key
     * @return
     */
public TreeNode deleteNode(TreeNode root, int key) {
    /*要删除的节点无左右孩子 即叶子节点 最简单 直接删除即可
       要删除的节点只有左孩子 左孩子替换当前节点
      要删除的节点只有右孩子 右孩子替换当前节点
      要删除的节点有左、右孩子  把左孩子放在 待删除节点右孩子最左边节点的左孩子上
         二叉搜索树后序是有序序列 待删除节点右孩子的最左边即是待删除节点的下一节点*/
    //迭代法更繁琐一些
    if(root == null) return root;
    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) {
            return root.right;
        }else if(root.right == null){
            return root.left;
        }else {
            TreeNode temp = root.right;
            while (temp.left != null){
                temp = temp.left;
            }
            temp.left = root.left;
            return root.right;
        }
    }
    return root;
}

修剪二叉搜索树

/**
     * leetcode-669  修剪二叉搜索树
     * @param root
     * @param low
     * @param high
     * @return
     */
public TreeNode trimBST(TreeNode root, int low, int high) {
    if(root == null) return root;
    if(root.val < low) {
        //return root.right; 不应该直接返回右子树 因为右子树中也有不符合条件的元素
        return trimBST(root.right,low,high); //而是应该继续往右子树寻找可用的节点
    }
    if(root.val > high) {
        //return root.left;
        return trimBST(root.left,low,high);
    }
    root.left = trimBST(root.left,low,high);
    root.right = trimBST(root.right,low,high);
    return root;
}

将有序数组转换为二叉搜索树

/**
     * leetcode-108. 将有序数组转换为二叉搜索树
     * @param nums
     * @return
     */
    public TreeNode sortedArrayToBST(int[] nums) {
        return sort(nums,0,nums.length-1);
    }

    public TreeNode sort(int[] nums,int start,int end){
        if(end < start) return null;
        int mid = (start+end)/2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = sort(nums,start,mid-1);
        root.right = sort(nums,mid+1,end);
        return root;
    }

把二叉搜索树转换为累加树

/**
     * leetcode-538. 把二叉搜索树转换为累加树
     * @param root
     * @return
     */
int pre = 0;
public TreeNode convertBST(TreeNode root) {
    if(root ==null) return root;
    pre(root);
    return root;
}

public void pre(TreeNode root){
    if(root == null) return;
    //先右 后中 再左
    pre(root.right);
    root.val += pre;
    pre = root.val;
    pre(root.left);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值