---
# System prepended metadata

title: CSPT23 Lecture 12

---

# CSPT23 Lecture 12
## [Max Depth](https://leetcode.com/problems/maximum-depth-of-binary-tree/)
```
from collections import deque
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    """
    Plan
    Use recursion to do a depth-first traversal and return the max depth you found
    """
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0
        self.maxDepthFoundSoFar = 0
        self.maxDepthHelper(root, 1)
        return self.maxDepthFoundSoFar
        
    def maxDepthHelper(self, node, depth):
        if node.left == None and node.right == None and depth > self.maxDepthFoundSoFar:
            self.maxDepthFoundSoFar = depth
            return
        if node.left:
            self.maxDepthHelper(node.left, depth + 1)
        if node.right:
            self.maxDepthHelper(node.right, depth + 1)
        
    def maxDepthLevelOrder(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0
        queue = deque()
        queue.append((root, 1))
        maxDepthFoundSoFar = 0
        while len(queue) > 0:
            curr = queue.popleft()
            currNode, currDepth = curr[0], curr[1]
            if currDepth > maxDepthFoundSoFar:
                maxDepthFoundSoFar = currDepth
            if currNode.left:
                queue.append((currNode.left, currDepth + 1))
            if currNode.right:
                queue.append((currNode.right, currDepth + 1))
        return maxDepthFoundSoFar
    
    def maxDepthIterativeDepthFirst(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0
        stack = deque()
        stack.append((root, 1))
        maxDepthFoundSoFar = 0
        while len(stack) > 0:
            curr = stack.pop()
            currNode, currDepth = curr[0], curr[1]
            if currDepth > maxDepthFoundSoFar:
                maxDepthFoundSoFar = currDepth
            if currNode.right:
                stack.append((currNode.right, currDepth + 1))
            if currNode.left:
                stack.append((currNode.left, currDepth + 1))
        return maxDepthFoundSoFar
```

## [Kth Smallest](https://leetcode.com/problems/kth-smallest-element-in-a-bst/)
```
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
from collections import deque
class Solution:
    """
    brute-force
    traverse the entire tree and push the values onto a list
    sort that list, return the k - 1 index
    runtime: O(nlogn)
    space: O(n)
    
    better approach
    do an inorder traversal and append values to the list, index
    correctly into the list afterwards
    runtime: O(n)
    space: O(n)
    
    best approach
    do an inorder traversal and keep track of how many nodes you've processed
    once you're processing the kth node, then you know that's the kth smallest
    value
    runtime: O(n)
    space: O(n)
    """
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        self.curr = 0
        return self.kthSmallestHelper(root, k)
    
    def kthSmallestHelper(self, node, k): # returns None or the kth node's value
        if node.left:
            leftSubtree = self.kthSmallestHelper(node.left, k)
            if leftSubtree != None:
                return leftSubtree
        
        self.curr += 1
        if self.curr == k:
            return node.val
        
        if node.right:
            rightSubtree = self.kthSmallestHelper(node.right, k)
            if rightSubtree != None:
                return rightSubtree
    
    def kthSmallestRecursiveNonOptimal(self, root: Optional[TreeNode], k: int) -> int:
        values = []
        self.kthSmallestHelperRecursiveNonOptimal(root, values)
        return values[k - 1]
        
    def kthSmallestHelperRecursiveNonOptimal(self, node, values):
        if node.left:
            self.kthSmallestHelper(node.left, values)
        values.append(node.val)
        if node.right:
            self.kthSmallestHelper(node.right, values)
    
    def kthSmallestBruteForce(self, root: Optional[TreeNode], k: int) -> int:
        values = []
        stack = deque()
        stack.append(root)
        while len(stack) > 0:
            curr = stack.pop()
            values.append(curr.val)
            if curr.left:
                stack.append(curr.left)
            if curr.right:
                stack.append(curr.right)
        values.sort()
        return values[k - 1]
```