【每日三题】二叉搜索树节点最小距离

183 阅读3分钟

每日三刷,剑指千题

计划简介:

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

说明:

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

[230]二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

示例 1:

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

解析

第一遍没想明白index++的位置,缕了一遍之后更深刻的理解了深度优先搜索。

Code

class Solution {
    int ans = 0;
    int index = 1;
    public int kthSmallest(TreeNode root, int k) {
        dfs(root,k);
        return ans;
    }
    void dfs(TreeNode root,int k){
        if (root == null)return;
        dfs(root.left,k);
        if (index == k){
            ans = root.val;
        }
        index++;
        dfs(root.right,k);
    }
}

[783]二叉搜索树节点最小距离

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:

img

输入:root = [4,2,6,1,3]
输出:1

注意: 本题与 530:leetcode-cn.com/problems/mi… 相同

解析

首先要明白一个问题是,对于二叉搜索树,采用中序遍历即从小到大排序,那遍历完之后的最小值只可能出现在相邻的两个元素。

所以思路就是先遍历得到排好序的列表,相邻元素相减,再比较最小值。

这样可以通过但效率不高,需要边遍历,边比较。

Code

class Solution {
    Stack<Integer> temp = new Stack();
    int ans = 9999999;
    public int minDiffInBST(TreeNode root) {
        temp.push(-9999999);
        dfs(root);
        return ans;
    }
​
    void dfs(TreeNode root){
        if (root == null)return;
        dfs(root.left);
        ans = Math.min(ans,root.val-temp.pop());
        temp.push(root.val);
        dfs(root.right);
    }
}

[863]二叉树中所有距离为 K 的结点

给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 k

返回到目标结点 target 距离为 k 的所有结点的值的列表。 答案可以以 任何顺序 返回。

示例 1:

img

输入:root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 2
输出:[7,4,1]
解释:所求结点为与目标结点(值为 5)距离为 2 的结点,值分别为 7,4,以及 1

解析

从给的案例可以看出,5到7,4是比较容易的,5到3的就不太容易了。

那如何把目标节点看作根节点呢?

先找出root和目标节点的距离吗?

那就应该还是层序遍历。

搞了半天,发现不行,看完官方的题解,还是不懂,稍后慢慢消化吧。

Code

class Solution {
    Map<Integer, TreeNode> parents = new HashMap<Integer, TreeNode>();
    List<Integer> ans = new ArrayList<Integer>();
​
    public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
        // 从 root 出发 DFS,记录每个结点的父结点
        findParents(root);
​
        // 从 target 出发 DFS,寻找所有深度为 k 的结点
        findAns(target, null, 0, k);
​
        return ans;
    }
​
    public void findParents(TreeNode node) {
        if (node.left != null) {
            parents.put(node.left.val, node);
            findParents(node.left);
        }
        if (node.right != null) {
            parents.put(node.right.val, node);
            findParents(node.right);
        }
    }
​
    public void findAns(TreeNode node, TreeNode from, int depth, int k) {
        if (node == null) {
            return;
        }
        if (depth == k) {
            ans.add(node.val);
            return;
        }
        if (node.left != from) {
            findAns(node.left, node, depth + 1, k);
        }
        if (node.right != from) {
            findAns(node.right, node, depth + 1, k);
        }
        if (parents.get(node.val) != from) {
            findAns(parents.get(node.val), node, depth + 1, k);
        }
    }
}

\