---
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: