LeetCode-230-二叉搜索树中第K小的元素


题意描述:

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

进阶:
如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化 kthSmallest 函数?


示例:

示例一:

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

示例二:

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

解题思路:

Alice🦄: 又是二叉树哦 ?
Bob 🐘:可以直接暴力做呀,前面不是做过一道 求 数组的 第 k 小的数嘛。可以先遍历二叉树,把结果存在数组中,然后再排序,再得到 第 k 小的数。
Alice🦄: 你这是把一个新的问题转换成一个已经解决过的问题对吗 ?不过这样的话二叉搜索树本身的信息 岂不是没有用到吗 ?
Bob🐘: 是啊,所以应该有更简洁的办法去 寻找 二叉搜索树 的第 k 个最小值。
Alice🦄: 二叉搜索树的性质是 左子树的所有值都比 根节点 小,右子树的所有值都比根节点大。然后还有,
Bob🐘: 如果是 找二叉搜索树的最小值,可以找到最深的 那棵左子树 的叶节点就是答案。可是怎么找到第 k 小的值呢 ? 能不能遍历完二叉搜索树之后直接得到一个有序的数组呢 ?
Alice🦄: 有了 (o゜▽゜)o☆,二叉树的前序遍历, 只要在递归的时候先访问二叉搜索树的左子树,然后根节点,最后访问右子树得到的遍历结果就是有序数组 !!!
Bob🐘: 哇,(✧◡✧)
Alice🦄: 😎


代码:

Python 方法一: 暴力求解,遍历二叉搜索树的所有值,排序,得到第K小的值。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:

    
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.values = []
        self.getAllNodes(root)
        self.values.sort()
        return self.values[k-1]
 
    def getAllNodes(self, root):
        if root == None:
            return 
        else:
            self.values.append(root.val)
            self.getAllNodes(root.left)
            self.getAllNodes(root.right)

Java 方法一:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public int kthSmallest(TreeNode root, int k) {
        List<Integer> values = new ArrayList();
        this.getAllNodes(root, values);
        int[] tmp = new int[values.size()];
        for(int i=0; i<values.size(); ++i){
            tmp[i] = values.get(i);
        }
        Arrays.sort(tmp);
        return tmp[k-1];
    }
    public void getAllNodes(TreeNode root, List<Integer> values){
        if(root == null){
            return ;
        }else{
            values.add(root.val);
            this.getAllNodes(root.left, values);
            this.getAllNodes(root.right, values);
        }
    }
}

Python 方法二: 深度优先搜索,就是说遍历二叉树的时候,先左子树,再根节点,再右子树。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:

    
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.values = []
        self.getAllNodes(root)
        return self.values[k-1]
  
    def getAllNodes(self, root):
        if root == None:
            return 
        else:
            self.getAllNodes(root.left)
            self.values.append(root.val)
            self.getAllNodes(root.right)

Python 方法二: dfs + 优化。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.values = []
        self.helper(root, k)
        return self.values[k-1]

    def helper(self, root, k):
        if root == None or len(self.values) == k:
            return
        else:
            self.helper(root.left, k)
            self.values.append(root.val)
            self.helper(root.right, k)

Python 方法二: 再优化一下空间复杂度。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.cnt = 1
        self.ans = 0
        self.helper(root, k)
        return self.ans
    
    def helper(self, root, k):
        if root == None or self.cnt > k:
            return
        else:
            self.helper(root.left, k)
            if self.cnt == k:
                self.ans = root.val
            self.cnt += 1
            self.helper(root.right, k)

Java 方法二: 深度优先搜索, dfs

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public int kthSmallest(TreeNode root, int k) {
        List<Integer> values = new ArrayList();
        this.getAllNodes(root, values);
        return values.get(k-1);
    }
    public void getAllNodes(TreeNode root, List<Integer> values){
        if(root == null){
            return ;
        }else{
            this.getAllNodes(root.left, values);
            values.add(root.val);
            this.getAllNodes(root.right, values);
        }
    }
}

Java 方法二: dfs + 优化 (提前终止遍历)。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public int kthSmallest(TreeNode root, int k) {
        List<Integer> values = new ArrayList();
        this.getAllNodes(root, k, values);
        return values.get(k-1);
    }
    public void getAllNodes(TreeNode root, int k, List<Integer> values){
        if(root == null || values.size() >= k){
            return ;
        }else{
            this.getAllNodes(root.left, k, values);
            values.add(root.val);
            this.getAllNodes(root.right, k, values);
        }
    }
}

Java 方法二: dfs + 时间复杂度优化 + 空间复杂度优化。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    int cnt = 0;
    int ans = 0;
    public int kthSmallest(TreeNode root, int k) {
        this.helper(root, k);
        return this.ans;
    }
    public void helper(TreeNode root, int k){
        if(this.cnt > k || root == null){
            return;
        }else{
            this.helper(root.left, k);

            this.cnt += 1;
            if(this.cnt == k){
                this.ans = root.val;
            }

            this.helper(root.right, k);
        }
    } 
}

易错点:

  • 一些测试样例:
[3,1,4,null,2]
4
[5,3,6,2,4,null,null,1]
3
  • 答案:
4
3

总结:

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值