Skip to content

Commit 5fb743d

Browse files
Add 'Kth Smallest Element in a BST'
1 parent 6d7e427 commit 5fb743d

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ A collection of LeetCode solutions
3030

3131
[K Closest Points to Origin](./src/k_closest_points_to_origin.py)
3232

33+
[Kth Smallest Element in a BST](./src/kth_smallest_element_in_a_bst.py)
34+
3335
[Linked List Cycle](./src/linked_list_cycle.py)
3436

3537
[Longest Common Subsequence](./src/longest_common_subsequence.py)

src/kth_smallest_element_in_a_bst.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
230. Kth Smallest Element in a BST
3+
4+
https://leetcode.com/problems/kth-smallest-element-in-a-bst
5+
6+
NOTES
7+
* A property of a binary search tree is that an in-order traversal will yield
8+
all the nodes in ascending order, so we should be able to solve this in
9+
O(H + k), where H is the height of the tree.
10+
11+
The iterative in-order traversal felt like a natural fit, but I implemented the
12+
solution using recursion as well just to flex.
13+
"""
14+
15+
from collections import deque
16+
17+
from src.classes import TreeNode
18+
19+
20+
class Solution:
21+
def kthSmallest(self, root: TreeNode | None, k: int) -> int:
22+
stack: deque[TreeNode] = deque()
23+
curr: TreeNode | None = root
24+
count = 0
25+
26+
# The iterative in-order traversal is pretty simple:
27+
# 1. Go as far left as possible.
28+
# 2. Pop and visit the first node from the stack.
29+
# 3. Repeat the process with the first non-null right node, otherwise
30+
# continue popping nodes from the stack.
31+
while stack or curr:
32+
while curr:
33+
stack.append(curr)
34+
curr = curr.left
35+
curr = stack.pop()
36+
count += 1
37+
if count == k:
38+
return curr.val
39+
curr = curr.right
40+
41+
return -1
42+
43+
44+
class RecursiveSolution:
45+
def kthSmallest(self, root: TreeNode | None, k: int) -> int:
46+
def dfs(root: TreeNode | None) -> tuple[int, int]: # (count, value)
47+
if not root:
48+
return 0, -1
49+
50+
# Search the left subtree.
51+
left_count, left_val = dfs(root.left)
52+
53+
# If the kth element is found, propagate it up. This is a crucial
54+
# aspect of recursion, basically, the ability to pass information
55+
# back up the call stack once some condition has been met.
56+
if left_val != -1:
57+
return left_count, left_val
58+
59+
# Check if the current node is the kth element.
60+
curr_count = left_count + 1
61+
if curr_count == k:
62+
return curr_count, root.val
63+
64+
# Search the right subtree. It's important to note that since
65+
# searching the right subtree represents a branch in the recursive
66+
# logic, the count must also reflect this.
67+
right_count, right_val = dfs(root.right)
68+
69+
return curr_count + right_count, right_val
70+
71+
_, result = dfs(root)
72+
return result
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
230. Kth Smallest Element in a BST
3+
4+
https://leetcode.com/problems/kth-smallest-element-in-a-bst
5+
"""
6+
7+
from unittest import TestCase
8+
9+
from src.kth_smallest_element_in_a_bst import RecursiveSolution, Solution
10+
from tests.utils import create_binary_tree_from_list
11+
12+
13+
class TestSolution(TestCase):
14+
def test_1(self):
15+
exp = 1
16+
root = create_binary_tree_from_list([3, 1, 4, None, 2])
17+
assert Solution().kthSmallest(root, 1) == exp
18+
19+
def test_2(self):
20+
exp = 3
21+
root = create_binary_tree_from_list([5, 3, 6, 2, 4, None, None, 1])
22+
assert Solution().kthSmallest(root, 3) == exp
23+
24+
25+
class TestRecursiveSolution(TestCase):
26+
def test_1(self):
27+
exp = 1
28+
root = create_binary_tree_from_list([3, 1, 4, None, 2])
29+
assert RecursiveSolution().kthSmallest(root, 1) == exp
30+
31+
def test_2(self):
32+
exp = 3
33+
root = create_binary_tree_from_list([5, 3, 6, 2, 4, None, None, 1])
34+
assert RecursiveSolution().kthSmallest(root, 3) == exp

0 commit comments

Comments
 (0)