---
# System prepended metadata

title: 230. Kth Smallest Element in a BST
tags: [LeetCode]

---

---
tags: LeetCode
---

# 230. Kth Smallest Element in a BST
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?

輸入範本如下
```C#
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int KthSmallest(TreeNode root, int k) {
        
    }
}
```

### 直覺想法

1. 按照中序走訪 BST , 其數字會由小到大排列 , 因此只要全部走過一次 , 並且將值存入 List 中. 即可透過索引值去找到第 k 個小的數字
    ```C#
    112 ms	28.6 MB
    You are here!
    Your runtime beats 26.85 % of csharp submissions.
    public int KthSmallest(TreeNode root, int k)
    {
        List<int> list = new List<int>();
        TravelTree(root, list);
        return list[k - 1];

        void TravelTree(TreeNode node, List<int> collection)
        {
            if (node is null) return;
            TravelTree(node.left, collection);
            collection.Add(node.val);
            TravelTree(node.right, collection);
        }
    }
    ```
2. 搜尋方式採用使用 DFS , 走訪順序為中緒走訪 . 透過 k 去紀錄現在走到第幾個字 ,  
    - 使用遞迴
        ```C#
        92 ms	28.3 MB
        You are here!
        Your runtime beats 98.28 % of csharp submissions.
        public int KthSmallest(TreeNode root, int k)
        {
            return FindKthSmallest(root, ref k);

            int FindKthSmallest(TreeNode node, ref int target)
            {
                if (node is null) return -1;
                int v = FindKthSmallest(node.left, ref target);
                if (target == 0) return v; // 已經找到答案了 , 把答案上傳.
                if (--target == 0) return node.val; // 目前這個點是答案.
                return FindKthSmallest(node.right, ref target);
            }
        }
        ```
    - 使用 Stack 
        ```C#
        96 ms	28.2 MB
        You are here!
        Your runtime beats 94.09 % of csharp submissions.
        public int KthSmallest(TreeNode root, int k)
        {
            Stack<TreeNode> stack = new Stack<TreeNode>();
            TreeNode node = root;
            while (node != null || stack.Count != 0)
            {
                while (node != null)
                {
                    stack.Push(node);
                    node = node.left;
                }
                node = stack.Pop();
                if (--k == 0) return node.val;
                node = node.right;
            }
            throw new Exception("not found");
        }
        ```
3. 二分搜尋法 - 預先判斷左右子點的 node 數量 , 判斷第 K 小的數量在左右子樹哪一邊.
    - 若左子樹有 k 個以上(含)的 node , 代表第 k 小的 node 在左子樹
    - 若左子樹有 k - 1 個 node , 代表第 k 小的 node 是 root 自身
    - 若左子樹有 k - 2 個以下(含) node , 代表第 k 小的 node 在右子樹
    ```C#
    100 ms	28.2 MB
    You are here!
    Your runtime beats 85.96 % of csharp submissions.
    public int KthSmallest(TreeNode root, int k)
    {
        int count = CountNode(root.left);
        if (k <= count)
        {
            return KthSmallest(root.left, k);
        }
        else if (k > count + 1)
        {
            return KthSmallest(root.right, k - (count + 1));
        }
        return root.val;

        int CountNode(TreeNode node)
        {
            return node is null ? 0 : 1 + CountNode(node.left) + CountNode(node.right);
        }
    }
    ```









### Thank you! 

You can find me on

- [GitHub](https://github.com/s0920832252)
- [Facebook](https://www.facebook.com/fourtune.chen)

若有謬誤 , 煩請告知 , 新手發帖請多包涵

# :100: :muscle: :tada: :sheep: 
