leetcode打卡-二叉树II

目录

106. 从中序与后序遍历序列构造二叉树

112. 路径总和

404. 左叶子之和

513. 找树左下角的值

530. 二叉搜索树的最小绝对差

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

 98. 验证二叉搜索树

701. 二叉搜索树中的插入操作

700. 二叉搜索树中的搜索

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

236. 二叉树的最近公共祖先

 501. 二叉搜索树中的众数

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

669. 修剪二叉搜索树

 450. 删除二叉搜索树中的节点

 257. 二叉树的所有路径

110. 平衡二叉树

617. 合并二叉树

 654. 最大二叉树


106. 从中序与后序遍历序列构造二叉树

leetcode题目链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal

leetcode AC记录:

思路:中序遍历是左中右,后序遍历是左右中,按照这个顺序后序数组的末尾为根,然后找到根在中序数组中的位置,将中序数组分为左右子树,递归循环这个过程即可。

代码如下:

public TreeNode buildTree(int[] inorder, int[] postorder) {
        return buildTree(inorder, postorder, 0, inorder.length-1, 0, postorder.length - 1);
    }

    public TreeNode buildTree(int[] inorder, int[] postorder, int inBegin, int inEnd, int postBegin, int postEnd) {
        if(inBegin > inEnd || postBegin > postEnd) {
            return null;
        }

        TreeNode root = new TreeNode();
        root.val = postorder[postEnd];
        int rootIndex = getRootIndex(inorder, root.val, inBegin, inEnd);
        root.left = buildTree(inorder, postorder, inBegin, rootIndex-1 , postBegin, postBegin + rootIndex - inBegin -1);
        root.right = buildTree(inorder, postorder, rootIndex + 1, inEnd , postBegin + rootIndex - inBegin, postEnd - 1);
        return root;
    }

    public int getRootIndex(int[] arr, int val, int begin, int end) {
        while(begin <= end) {
            if(arr[begin] == val) {
                return begin;
            }
            begin++;
        }
        return -1;
    }

112. 路径总和

leetcode题目链接:https://leetcode.cn/problems/path-sum

leetcode AC记录: 

思路:使用回溯和递归,将当前节点的累加和传递到子树中,如果碰到叶子节点,判断和是否为目标值,如果是返回并将结果递归到上层,层层递归最终返回。

代码如下:

 public boolean hasPathSum(TreeNode root, int targetSum) {
        return pathSum(root, 0, targetSum);
    }

    public boolean pathSum(TreeNode node, int currentSum, int targetSum) {
        if(node == null) {
            return false;
        }
        currentSum += node.val;
        if(node.left == null && node.right == null && currentSum == targetSum) {
            return true;
        }

        boolean flag = false;
        if(node.left != null) {
            flag = pathSum(node.left, currentSum, targetSum);
            if(flag == true) {
                return true;
            }
        }

        if(node.right != null) {
            flag = pathSum(node.right, currentSum, targetSum);
            if(flag == true) {
                return true;
            }
        }

        return flag;
    }

404. 左叶子之和

leetcode题目链接:https://leetcode.cn/problems/sum-of-left-leaves/

leetcode AC记录:

思路:使用递归方式前序遍历,返回条件为遇到左右子树为空,如果判断遇到了左叶子节点,则累加左叶子节点的值。

代码如下:

public int sumOfLeftLeaves(TreeNode root) {
        if(root == null) {
            return 0;
        }

        if(root.left == null && root.right == null) {
            return 0;
        }

        int leftSum = sumOfLeftLeaves(root.left);
        if(root.left != null && root.left.left == null && root.left.right == null)  {
            leftSum = root.left.val;
        }

        int rightSum = sumOfLeftLeaves(root.right);

        return leftSum + rightSum;
    }

513. 找树左下角的值

leetcode题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/

leetcode AC记录:

思路:层序遍历,找到最后一层第一个元素即可。

代码如下:

public int findBottomLeftValue(TreeNode root) {
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int res = root.val;
        while(!queue.isEmpty()) {
            int size = queue.size();
            int index = 0;
            while(index < size) {
                TreeNode node = queue.pollFirst();
                if(index == 0) {
                    res = node.val;
                }
                index++;

                if(node.left != null) {
                    queue.offer(node.left);
                }

                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
        }
        return res;
    }

530. 二叉搜索树的最小绝对差

leetcode题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst

leetcode AC记录:

思路:使用中序迭代法遍历二叉树,因为是二叉搜索树,所以中序遍历是有序的,只需要记录上一个节点的值,和当前节点做差和最小差值进行比较赋值即可。

代码如下:

public int getMinimumDifference(TreeNode root) {
        TreeNode cur = root;
        int minDiff = Integer.MAX_VALUE;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while(!stack.empty() || cur != null) {
            if(cur != null) {
                stack.push(cur);
                cur = cur.left;
            } else {
                TreeNode node = stack.pop();
                if(pre != null && node != null) {
                    minDiff = Math.min(Math.abs(pre.val - node.val), minDiff);
                }
                pre = node;
                cur = node.right;
            }
        }
        return minDiff;
    }

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

leetcode题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree

leetcode AC记录:

思路:利用二叉搜索树的特性,左子树比根小,右子树比根大,如果根的值大于p并且大于q,说明公共祖先在当前节点的左子树中,如果根的值小于p并且小于q,说明公共祖先在当前节点的右子树中。

代码如下:

public TreeNode lowestCommonAncestor(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 null;
    }

 98. 验证二叉搜索树

leetcode题目链接:https://leetcode.cn/problems/validate-binary-search-tree

leetcode AC记录:

思路:递归判断。注意一点,只需要判断当前节点是否符合大于给定上限,小于给定下限,如果是左节点,上限为根节点的值,如果是右节点,下限为根节点的值。

代码如下:

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

    public boolean isValidBST(TreeNode root, long begin, long end) {
        if(root == null) {
            return true;
        }

        if(root.val <= begin || root.val >= end) {
            return false;
        }

        return isValidBST(root.left, begin, (long)root.val) && isValidBST(root.right, root.val, end);
    }

701. 二叉搜索树中的插入操作

leetcode题目链接:https://leetcode.cn/problems/insert-into-a-binary-search-tree/

leetcode AC记录:

思路:通过二叉搜索树的特点确定插入的位置,确定后作为叶子节点插入。

代码如下:

public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root == null) {
            return new TreeNode(val);
        }
        //确定插入的位置 true代表左 false代表右
        boolean flag = true;
        TreeNode res = root;
        TreeNode pre = root;
        while(root != null) {
            pre = root;
            if(root.val > val) {
                root = root.left;
                flag = true;
            } else if(root.val < val) {
                root = root.right;
                flag = false;
            } 
        }

        TreeNode node = new TreeNode(val);
        if(flag) {
            pre.left = node;
        } else {
            pre.right = node;
        }
        return res;
    }

700. 二叉搜索树中的搜索

 leetcode题目链接:https://leetcode.cn/problems/search-in-a-binary-search-tree/

leetcode AC记录:

思路:递归搜索。

代码如下:

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

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

leetcode题目链接:https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree

leetcode AC记录:

思路:二叉搜索树为有序的树,左子树比根小,右子树比根大,所以每次取数组中间节点当作根,然后将数组根据根节点位置分为左右子树,递归这个过程直到数组下标不符合要求(或者左右子树为空)。

代码如下:

 public TreeNode sortedArrayToBST(int[] nums) {
        //取中间的作为根节点
        return buildTree(nums, 0, nums.length-1);
    }

    public TreeNode buildTree(int[] nums, int begin, int end) {
        if(begin < 0 || end >= nums.length || begin > end) {
            return null;
        }
        int mid = (end - begin) / 2 + begin;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = buildTree(nums, begin, mid - 1);
        root.right = buildTree(nums, mid + 1, end);

        return root;
    }

236. 二叉树的最近公共祖先

leetcode题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

leetcode AC记录:

思路:这道题有点难,使用前序遍历,如果当前节点包含q或者p,返回当前节点,如果左右子树都不为空返回结果(题目中的前提是肯定会包含p和q)。

代码如下:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == q || root == p || root == null) {
            return root;
        }

        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        if(left != null && right != null) {
            return root;
        } else if(left == null && right != null) {
            return right;
        } else if(left != null && right == null) {
            return left;
        } else {
            return null;
        }
    }   

 501. 二叉搜索树中的众数

leetcode题目链接:https://leetcode.cn/problems/find-mode-in-binary-search-tree/

leetcode AC记录:

思路:使用迭代法中序遍历,那么遍历过程是一个有序的数组,记录出现元素最多的次数maxCount,如果当前的次数大于maxCount,清空结果数组,将当前节点值放入结果数组;如果当前节点值次数等于maxCount,将当前节点放入结果数组。

代码如下:

public int[] findMode(TreeNode root) {
        List<Integer> list = new ArrayList<>(16);
        int maxCount = 0;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        Integer preval = null;
        int curCount = 1;
        while(!stack.empty() || cur != null) {
            if(cur != null) {
                stack.push(cur);
                cur = cur.left;
            }else {
                TreeNode node = stack.pop();
                if(preval == null) {
                    curCount = 1;
                }else if(node.val == preval) {
                    curCount++;
                } else {
                    curCount = 1;
                }

                if(maxCount < curCount) {
                    maxCount = curCount;
                    list.clear();
                    list.add(node.val);
                } else if(maxCount == curCount){
                    list.add(node.val);
                }

                preval = node.val;
                cur = node.right;
            }
        }

        return list.stream().mapToInt(Integer::valueOf).toArray();
    }

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

leetcode题目链接:https://leetcode.cn/problems/convert-bst-to-greater-tree/ 

leetcode AC记录:

思路:使用迭代法中序遍历,区别在于先遍历右节点,即右中左,遍历节点累加赋值即可。

代码如下:

public TreeNode convertBST(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        int sum = 0;
        while(!stack.empty() || cur != null) {
            if(cur != null) {
                stack.push(cur);
                cur = cur.right;
            }else {
                TreeNode node = stack.pop();
                sum += node.val;
                node.val = sum;
                cur = node.left;
            }
        }
        return root;
    }

669. 修剪二叉搜索树

leetcode题目链接:https://leetcode.cn/problems/trim-a-binary-search-tree/ 

leetcode AC记录:

思路:如果当前节点值在范围里,递归处理左右子树;如果当前节点值小于下限,根据二叉搜索树的特点,说明当前节点的左子树也不符合条件,返回当前节点的右子树并递归处理,当前节点大于上限同理处理。

代码如下:

 public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root == null) {
            return null;
        } else if(root.val >= low && root.val <= high) {
            root.left = trimBST(root.left, low, high);
            root.right = trimBST(root.right, low, high);
        } else if(root.val < low){
            return trimBST(root.right, low, high);
        } else if(root.val > high) {
            return trimBST(root.left, low, high);
        }

        return root;
    }

 450. 删除二叉搜索树中的节点

leetcode题目链接:https://leetcode.cn/problems/delete-node-in-a-bst/

leetcode AC记录:

思路:删除二叉搜索树的节点相对于增加节点难很多,删除后需要调整树的结构。难点在于递归的处理细节,刚开始写的时候我会想如果删除的是根节点该如何处理,其实出发点不对,只需要考虑当前节点该如何操作就行:如果当前节点大于key,递归删除左节点;如果当前节点小于key,递归删除右节点;如果当前节点等于key,需要删除当前节点。下面讨论下如何删除当前节点:

        如果当前节点的左右子树为空,说明删除的是叶子节点,直接返回空;

        如果当前节点的左右子树其中一个为空,返回不为空的;

        如果当前节点的左右子树都不为空,把右子树当作根,左子树应该放到右子树的最左的叶子节点处。

代码如下:

public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null) {
            return null;
        }else if(root.val > key) {
            root.left = deleteNode(root.left, key);
        } else if(root.val < key) {
            root.right = deleteNode(root.right, key);
        } else {
            if(root.left == null) {
                return root.right;
            } else if(root.right == null) {
                return root.left;
            } else {
                TreeNode res = root.right;
                TreeNode left = root.left;
                TreeNode right = root.right;
                while(right.left != null) {
                    right = right.left;
                }
                right.left = left;
                return res;
            }
        }

        return root;
    }

 257. 二叉树的所有路径

leetcode题目链接:https://leetcode.cn/problems/binary-tree-paths

leetcode AC记录:

思路:回溯和递归,递归用来遍历二叉树,回溯用来回退节点。

代码如下:

public List<String> binaryTreePaths(TreeNode root) {
        List<Integer> list = new ArrayList<>(16);
        List<String> res = new ArrayList<>(16);
        traversal(root, list, res);
        return res;
    }


    public void traversal(TreeNode node, List<Integer> path, List<String> res) {

        if(node == null) {
            return;            
        }

        path.add(node.val);
        if(node.left == null && node.right == null) {
            res.add(path.stream().map(String::valueOf).collect(Collectors.joining("->")));
            return;
        }

        if(node.left != null) {
            traversal(node.left, path, res);
            path.remove(path.size()-1);
        }

        if(node.right != null) {
            traversal(node.right, path, res);
            path.remove(path.size()-1);
        }
    }

110. 平衡二叉树

leetcode题目链接:https://leetcode.cn/problems/balanced-binary-tree

leetcode AC记录:

思路:使用后序递归遍历二叉树,返回条件为遇到空节点高度为0。分别判断左右子树的高度,高度是从叶子节点开始累加计算,如果高度差不符合要求返回-1。

代码如下:

public boolean isBalanced(TreeNode root) {
        return high(root) != -1;
    }

    public int high(TreeNode node) {
        if(node == null) return 0;

        int leftHeight = high(node.left);
        int rightHeight = high(node.right);
        
        if(leftHeight == -1 || rightHeight == -1) {
            return -1;
        }

        int abs = Math.abs(leftHeight - rightHeight);
        if(abs > 1) {
            return -1;
        }

        return Math.max(leftHeight, rightHeight) + 1;
    }

617. 合并二叉树

leetcode题目链接:https://leetcode.cn/problems/merge-two-binary-trees/

leetcode AC记录:

思路:递归合并,如果树1为空,返回树2;如果树2为空,返回树1;如果都不为空,树1的节点值累加树2的值,最后返回树1的根。

代码如下:

public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if(root1 == null && root2 == null) {
            return null;
        } else if(root1 == null && root2 != null) {
            return root2;
        } else if(root1 != null && root2 == null) {
            return root1;
        }

        if(root1 != null && root2 != null) {
            root1.val += root2.val;
            root1.left = mergeTrees(root1.left, root2.left);
            root1.right = mergeTrees(root1.right, root2.right);
        }

        return root1;
    }

 654. 最大二叉树

leetcode题目链接:https://leetcode.cn/problems/maximum-binary-tree/

leetcode AC记录:

思路:递归,和使用数组构建二叉搜索树类似。

代码如下:

public TreeNode constructMaximumBinaryTree(int[] nums) {
        return construct(nums, 0, nums.length-1);
    }

    public TreeNode construct(int[] nums, int beginIndex, int endIndex) {
        if(beginIndex < 0 || endIndex >= nums.length || beginIndex > endIndex) {
            return null;
        }
        int maxIndex = maxIndex(nums, beginIndex, endIndex);
        TreeNode root = new TreeNode(nums[maxIndex]);
        root.left = construct(nums, beginIndex, maxIndex-1);
        root.right = construct(nums, maxIndex+1, endIndex);
        return root;
    }

    public int maxIndex(int[] nums, int beginIndex, int endIndex) {
        int index = beginIndex;
        while(++beginIndex <= endIndex) {
            if(nums[index] < nums[beginIndex]) {
                index = beginIndex;
            }
        }
        return index;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值