Problem#
Given the root
of a binary search tree (BST) with duplicates, return all themode(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:
The left subtree of a node contains only nodes with keys less than or equal to the node’s key.
The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
Both the left and right subtrees must also be binary search trees.
Examples#
Example 1#
1
2
3
4
5

Input: root = [ 1 , null , 2 , 2 ]
Output: [ 2 ]
Example 2#
1
2
Input: root = [ 0 ]
Output: [ 0 ]
Constraints#
The number of nodes in the tree is in the range [1, 10^4]
.
-10^5 <= Node.val <= 10^5
Follow up: Could you do that without using any extra space? (Assume that
the implicit stack space incurred due to recursion does not count).
Solution#
Method 1 – Inorder Traversal with Frequency Counting#
Intuition#
Since the tree is a BST, an inorder traversal visits nodes in sorted order. We can count the frequency of each value as we traverse, and track the mode(s) by keeping the maximum frequency seen so far.
Approach#
Perform an inorder traversal of the BST.
Use a variable to track the previous value, a counter for the current value, and a variable for the maximum frequency.
When visiting a node:
If the value is the same as the previous, increment the counter.
Otherwise, reset the counter to 1.
If the counter equals the max frequency, add the value to the answer list.
If the counter exceeds the max frequency, reset the answer list and update the max frequency.
Return the answer list at the end.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct TreeNode {
int val;
TreeNode * left;
TreeNode * right;
};
class Solution {
public :
vector< int > findMode(TreeNode* root) {
vector< int > ans;
int maxFreq = 0 , curFreq = 0 , prev = INT_MIN;
function< void (TreeNode* )> inorder = [& ](TreeNode* node) {
if (! node) return ;
inorder(node-> left);
if (node-> val == prev) curFreq++ ;
else curFreq = 1 ;
if (curFreq == maxFreq) ans.push_back(node-> val);
else if (curFreq > maxFreq) {
ans = {node-> val};
maxFreq = curFreq;
}
prev = node-> val;
inorder(node-> right);
};
inorder(root);
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type TreeNode struct {
Val int
Left * TreeNode
Right * TreeNode
}
func findMode (root * TreeNode ) []int {
var ans []int
var maxFreq , curFreq int
var prev * int
var inorder func (* TreeNode )
inorder = func (node * TreeNode ) {
if node == nil { return }
inorder (node .Left )
if prev != nil && node .Val == * prev {
curFreq ++
} else {
curFreq = 1
}
if curFreq == maxFreq {
ans = append(ans , node .Val )
} else if curFreq > maxFreq {
ans = []int {node .Val }
maxFreq = curFreq
}
v := node .Val
prev = & v
inorder (node .Right )
}
inorder (root )
return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class TreeNode {
int val;
TreeNode left, right;
}
class Solution {
private Integer prev = null ;
private int maxFreq = 0, curFreq = 0;
private List< Integer> ans = new ArrayList<> ();
public int [] findMode (TreeNode root) {
inorder(root);
return ans.stream ().mapToInt (i-> i).toArray ();
}
private void inorder (TreeNode node) {
if (node == null ) return ;
inorder(node.left );
if (prev != null && node.val == prev) curFreq++ ;
else curFreq = 1;
if (curFreq == maxFreq) ans.add (node.val );
else if (curFreq > maxFreq) {
ans.clear (); ans.add (node.val ); maxFreq = curFreq;
}
prev = node.val ;
inorder(node.right );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
data class TreeNode (var `val`: Int, var left: TreeNode? = null , var right: TreeNode? = null )
class Solution {
private var prev: Int? = null
private var maxFreq = 0
private var curFreq = 0
private val ans = mutableListOf<Int>()
fun findMode (root: TreeNode?): IntArray {
inorder(root)
return ans.toIntArray()
}
private fun inorder (node: TreeNode?) {
if (node == null ) return
inorder(node.left)
if (prev != null && node.`val` == prev) curFreq++ else curFreq = 1
if (curFreq == maxFreq) ans.add(node.`val`)
else if (curFreq > maxFreq) {
ans.clear(); ans.add(node.`val`); maxFreq = curFreq
}
prev = node.`val`
inorder(node.right)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class TreeNode :
def __init__ (self, val= 0 , left= None , right= None ):
self. val = val
self. left = left
self. right = right
class Solution :
def findMode (self, root: TreeNode) -> list[int]:
ans = []
max_freq = cur_freq = 0
prev = None
def inorder (node):
nonlocal prev, cur_freq, max_freq, ans
if not node: return
inorder(node. left)
if prev is not None and node. val == prev:
cur_freq += 1
else :
cur_freq = 1
if cur_freq == max_freq:
ans. append(node. val)
elif cur_freq > max_freq:
ans = [node. val]
max_freq = cur_freq
prev = node. val
inorder(node. right)
inorder(root)
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn find_mode (root: Option< Rc< RefCell< TreeNode>>> ) -> Vec< i32 > {
fn inorder (node: Option< Rc< RefCell< TreeNode>>> , prev: & mut Option< i32 > , cur_freq: & mut i32 , max_freq: & mut i32 , ans: & mut Vec< i32 > ) {
if let Some(n) = node {
let n = n.borrow();
inorder(n.left.clone(), prev, cur_freq, max_freq, ans);
if let Some(p) = prev {
if n.val == * p { * cur_freq += 1 ; } else { * cur_freq = 1 ; }
} else { * cur_freq = 1 ; }
if * cur_freq == * max_freq { ans.push(n.val); }
else if * cur_freq > * max_freq {
ans.clear(); ans.push(n.val); * max_freq = * cur_freq;
}
* prev = Some(n.val);
inorder(n.right.clone(), prev, cur_freq, max_freq, ans);
}
}
let mut prev = None;
let mut cur_freq = 0 ;
let mut max_freq = 0 ;
let mut ans = vec! [];
inorder(root, & mut prev, & mut cur_freq, & mut max_freq, & mut ans);
ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class TreeNode {
val : number ;
left : TreeNode | null ;
right : TreeNode | null ;
constructor (val? : number , left? : TreeNode | null , right? : TreeNode | null ) {
this .val = val ?? 0 ;
this .left = left ?? null ;
this .right = right ?? null ;
}
}
class Solution {
findMode (root : TreeNode | null ): number [] {
let ans : number [] = [];
let maxFreq = 0 , curFreq = 0 , prev : number | null = null ;
function inorder (node : TreeNode | null ) {
if (! node ) return ;
inorder (node .left );
if (prev !== null && node .val === prev ) curFreq ++ ;
else curFreq = 1 ;
if (curFreq === maxFreq ) ans .push (node .val );
else if (curFreq > maxFreq ) {
ans = [node .val ];
maxFreq = curFreq ;
}
prev = node .val ;
inorder (node .right );
}
inorder (root );
return ans ;
}
}
Complexity#
⏰ Time complexity: O(n)
, where n is the number of nodes in the tree. Each node is visited once.
🧺 Space complexity: O(h)
, where h is the height of the tree due to recursion stack.