Leetcode 230:二叉搜索树中第K小的元素(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/82423465

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

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

示例 1:

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

示例 2:

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

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

解题思路

我们首先想到的方法是对这个树排序,然后取第k小的元素即可。但是怎么对一颗树排序呢?遍历一棵树,然后将遍历的结果存在一个list里面,然后对这个list排序。我们要解决的问题就是如何遍历一颗树

Leetcode 144:二叉树的前序遍历(最优雅的解法!!!)

Leetcode 94:二叉树的中序遍历(最优雅的解法!!!)

Leetcode 145:二叉树的后序遍历(最详细的解法!!!)

Leetcode 112:路径总和(最详细的解法!!!)

我这里以前序遍历为例,写出如下操作

class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        result = list()
        stack = [root]
        while len(stack):
            top = stack.pop()
            if top.right:
                stack.append(top.right)

            if top.left:
                stack.append(top.left)

            result.append(top.val)

        result.sort()
        return result[k-1]

但是有没有更快地算法呢?有没有办法,在遍历的过程中就知道list的排序呢?啊!!!中序遍历。我们知道中序遍历的结果是一个有序的list,所以我们可以在中序遍历中设置提前停止。

class Solution:
    def _inOrder(self, root, arr, k):
        if root:
            self._inOrder(root.left, arr, k)
            if len(arr) >= k:
                return

            arr.append(root.val)
            self._inOrder(root.right, arr, k)

    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        result = list()
        self._inOrder(root, result, k)
        return result[k - 1]

同样的,对于递归可以解决的问题,我都希望可以通过迭代去解决。这个问题很容易,也就是写出中序遍历的迭代形式。

class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        result = list()
        stack = list()
        while stack or root:
            if root:
                stack.append(root)
                root = root.left
            else:
                root = stack.pop()
                result.append(root.val)
                if len(result) >= k:
                    break
                root = root.right

        return result[k-1]

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/82423465