# 230. Kth Smallest Element in a BST

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/

> 内容描述

```
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

Note: 
You may assume k is always valid, 1 ≤ k ≤ BST's total elements.

Example 1:

Input: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
Output: 1
Example 2:

Input: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
Output: 3
Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******


跟昨天做的一道题类似，一上来就走取巧之路。

InOrder排序，输出，当然也完全可以用昨天的binary tree iterator,入stack,出stack,直到输出第k位


```python
class Solution(object):
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        self.root = root
        self.lst = []
        self.inOrder(root)
        return self.lst[k-1]

    def inOrder(self, root):
        if root == None:
            return
        self.inOrder(root.left)
        self.lst.append(root.val)
        self.inOrder(root.right)
```

> 思路 2
******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******

现在看到kth 就条件反射的想用divide & conquer, 扫root的左子树看nodes量，如果nodes数量是k-1，那么root就刚好是第k个，如果大于k > 左子树数量，扫右子树，同时更新root为root.right。

看到的言论：

> If we can change the BST node structure, We can add a new Integer to mark the number of element in the left sub-tree.

when the node is not null.

- if k == node.leftNum + 1, return node
- if k > node.leftNum + 1, make k -= node.leftNum + 1, and then node = node.right
- otherwise, node = node.left


```python
class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        def count(node):
            if not node:
                return 0
            return count(node.left) + count(node.right) + 1
        
        if not root:
            return None
        left = count(root.left)
        if left == k - 1:
            return root.val
        elif left > k - 1:
            return self.kthSmallest(root.left, k)
        else:
            return self.kthSmallest(root.right, k - left - 1)
```
