Given the root
of a binary search tree (BST) with duplicates, return all the mode(s) (i.e., the most frequently occurred element) in it.
If the tree has more than one mode, return them in any order.
Assume a BST is defined as follows:
Example 1:
Input: root = [1,null,2,2] Output: [2]
Example 2:
Input: root = [0] Output: [0]
Constraints:
[1, 104]
.-105 <= Node.val <= 105
Follow up: Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count).
This problem asks to find the mode(s) (most frequent element(s)) in a Binary Search Tree (BST) that may contain duplicate values. The solution uses a depth-first search (DFS) approach with in-order traversal to efficiently find the mode. The key to optimization is leveraging the property of a BST, where elements are sorted during an inorder traversal.
In-order Traversal: We perform an in-order traversal of the BST. In-order traversal visits nodes in ascending order of their values. This is crucial because it allows us to easily count consecutive occurrences of the same value.
Counting Consecutive Occurrences: We maintain three variables:
cnt
: Counts the consecutive occurrences of the current node's value.mx
: Stores the maximum frequency encountered so far.prev
: Stores the previously visited node.Updating Mode:
prev
), we increment cnt
.cnt
to 1.cnt
exceeds mx
, it means we've found a new mode with higher frequency, so we update mx
and reset the result list ans
with the current node's value.cnt
equals mx
, it means we've found another mode with the same highest frequency, so we append the current node's value to ans
.Returning the Mode(s): After the traversal, ans
contains all the modes of the BST.
Time Complexity: O(N), where N is the number of nodes in the BST. This is because we perform a single in-order traversal of the tree, visiting each node exactly once.
Space Complexity: O(H) in the worst case, and O(log N) on average, where H is the height of the tree. This space is used for the recursive call stack during the DFS. In the worst-case scenario (a skewed tree), H can be equal to N, resulting in O(N) space complexity. However, in a balanced BST, the height is logarithmic with respect to the number of nodes, leading to O(log N) average space complexity. The space used for the ans
list is at most O(N) in the worst case (all nodes have the same value).
The Python code efficiently implements this approach. Note the use of nonlocal keyword to modify variables outside the scope of inner function dfs
.
class Solution:
def findMode(self, root: TreeNode) -> List[int]:
def dfs(root):
if root is None:
return
nonlocal mx, prev, ans, cnt
dfs(root.left)
cnt = cnt + 1 if prev == root.val else 1
if cnt > mx:
ans = [root.val]
mx = cnt
elif cnt == mx:
ans.append(root.val)
prev = root.val
dfs(root.right)
prev = None
mx = cnt = 0
ans = []
dfs(root)
return ans
The other languages (Java, C++, Go, C#) follow a similar structure, adapting the syntax and data structures to their respective languages. The core algorithm remains the same, ensuring efficient in-order traversal and mode calculation.