【每日三题】二叉树的坡度,在二叉树中增加一行

85 阅读4分钟

每日三刷,剑指千题

计划简介:

  • 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
  • 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
  • 每日中午进行编码,时间控制在一小时之内。
  • 下班前半小时进行整理总结,并发布到掘金每日更文活动。

说明:

  • 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
  • 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
  • 刷题过程中整理相似题型,刷题模板。
  • 目前进度 133/1000

[剑指 Offer 54]二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

示例 1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 4

解析

简单思路就是遍历再排序,能过,但效率不高。

仔细一看,忽略了二叉搜索树这一条件,也就是说按照中序遍历,二叉树是按升序排好序的。

但只需中序倒序遍历即可,同时 k-- ,当 k=0 时,即找到答案。

这样的好处可以提前结束遍历。

Code

class Solution {
        List ans = new ArrayList<Integer>();
​
        public int kthLargest(TreeNode root, int k) {
            traverse(root);
            Collections.sort(ans);
            return (int) ans.get(ans.size() - k);
        }
​
        private void traverse(TreeNode root) {
            if (root != null) {
                ans.add(root.val);
                traverse(root.left);
                traverse(root.right);
            }
​
        }
    }
class Solution {
        int res;
        int index = 0; //计数器
​
        public int kthLargest(TreeNode root, int k) {
            dfs(root, k);
            return res;
        }
​
        void dfs(TreeNode root, int k) {
            if (root == null) return;
            dfs(root.right, k); //右
            index++;
            if (k == index) res = root.val; //根
            dfs(root.left, k); //左
        }
​
    }

[623]在二叉树中增加一行

给定一个二叉树的根 root 和两个整数 valdepth ,在给定的深度 depth 处添加一个值为 val 的节点行。

注意,根节点 root 位于深度 1

加法规则如下:

  • 给定整数 depth,对于深度为 depth - 1 的每个非空树节点 cur ,创建两个值为 val 的树节点作为 cur 的左子树根和右子树根。
  • cur 原来的左子树应该是新的左子树根的左子树。
  • cur 原来的右子树应该是新的右子树根的右子树。
  • 如果 depth == 1意味着 depth - 1 根本没有深度,那么创建一个树节点,值 val作为整个原始树的新根,而原始树就是新根的左子树。

示例 1:

输入: root = [4,2,6,3,1,5], val = 1, depth = 2
输出: [4,1,1,2,null,null,6,3,1,5]

解析

看着很复杂,实际就是层序遍历的一个变形,试着写了一下,竟然超过100%,牛批!

Code

class Solution {
    public TreeNode addOneRow(TreeNode root, int val, int depth) {
        if (depth == 1){
            return new TreeNode(val,root,null);
        }
        int index = 1;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            int n = queue.size();
            for (int i = 0; i < n; i++) {
                TreeNode node = queue.poll();
                // 拼接处理
                if (index == depth - 1){
                    TreeNode left = node.left;
                    TreeNode right = node.right;
                    node.left = new TreeNode(val,left,null);
                    node.right = new TreeNode(val,null,right);
                }else {
                    if(node.left!=null){
                        queue.offer(node.left);
                    }
                    if(node.right!=null){
                        queue.offer(node.right);
                    }
                }
            }
            // 没有break,效率也很高
            index++;
        }
        return root;
    }
}

[563]二叉树的坡度

给你一个二叉树的根节点 root ,计算并返回 整个树 的坡度 。

一个树的 节点的坡度 定义即为,该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话,左子树的节点之和为 0 ;没有右子树的话也是一样。空结点的坡度是 0 。

整个树 的坡度就是其所有节点的坡度之和。

示例 1:

输入:root = [1,2,3]
输出:1
解释:
节点 2 的坡度:|0-0| = 0(没有子节点)
节点 3 的坡度:|0-0| = 0(没有子节点)
节点 1 的坡度:|2-3| = 1(左子树就是左子节点,所以和是 2 ;右子树就是右子节点,所以和是 3 )
坡度总和:0 + 0 + 1 = 1

解析

看了题解是明白了,可自己还是想不起来,还得练。

Code

class Solution {
        int ans = 0;
        public int findTilt(TreeNode root) {
            dfs(root);
            return ans;
        }
​
        int dfs(TreeNode root){
            if (root==null)return 0;
            int l = dfs(root.left);
            int r = dfs(root.right);
            ans += Math.abs(r-l);
            return root.val + l+r;
        }
    }

\