Problem Statement
Given the root
node of a binary search tree (BST) and an integer k
. Return the kth
smallest and largest value (1-indexed) of all values of the nodes in the tree.
Examples
Example 1:
Input: root = [3, 1, 4, null, 2], k = 1
Output: [1, 4]
Explanation: The 1st smallest value in given BST is 1.
The 1st largest value in given BST is 4.
Example 2:
Input: root = [5, 3, 6, 2, null, null, null, 1], k = 3
Output: [3, 3]
Explanation: The 3rd largest value in the BST is 3.
The 3rd largest value int BST is 3.
Different Approaches
1️⃣ Brute Force Approach
Intuition:
To find the Kth smallest and largest elements in a Binary Search Tree (BST) using a brute force method, a simple approach is to traverse the tree and collect all its node values in a list. or a vector. By sorting this list, the desired elements can be easily retrieved based on their indices. To find the Kth smallest element, access the element at index ‘k - 1’ in the array, and to find the Kth largest element, access the element at index ‘array.length - K’ index. Note that it is preferred to consider the inorder traversal of the BST because it will come out to be sorted already.
Approach:
- Begin by creating a list or vector to serve as a storage container for the values of the nodes present in the Binary Search Tree (BST).
- Perform an inorder traversal of the BST utilizing the depth-first search (DFS) technique, during which each node's value should be added to the previously initialized array.
- To identify the Kth smallest element, retrieve the element located at the index 'k - 1' of the sorted array, keeping in mind that array indexing begins at zero.
- To determine the Kth largest element, retrieve the element positioned at the index 'array.length - k' within the sorted array.
- Finally, return a pair of elements: the Kth smallest and the Kth largest, as determined by the aforementioned steps.
Code:
#include <bits/stdc++.h>
using namespace std;
// Definition for a binary tree node.
struct TreeNode {
int data;
TreeNode *left;
TreeNode *right;
TreeNode(int val) : data(val), left(nullptr), right(nullptr) {}
};
class Solution {
public:
// Helper function to perform an in-order traversal of the BST
void inorderTraversal(TreeNode* node, vector<int>& values) {
if (node) {
inorderTraversal(node->left, values);
values.push_back(node->data);
inorderTraversal(node->right, values);
}
}
vector<int> kLargesSmall(TreeNode* root, int k) {
// Vector to store the node values
vector<int> values;
// Perform in-order traversal and collect values
inorderTraversal(root, values);
// Find the kth smallest and kth largest values
int kth_smallest = values[k - 1];
int kth_largest = values[values.size() - k];
return {kth_smallest, kth_largest};
}
};
// Main method to demonstrate the function
int main() {
// Constructing the tree: [3, 1, 4, null, 2]
TreeNode* root = new TreeNode(3);
root->left = new TreeNode(1);
root->left->right = new TreeNode(2);
root->right = new TreeNode(4);
Solution solution;
int k = 1;
vector<int> result = solution.kLargesSmall(root, k);
cout << "[" << result[0] << ", " << result[1] << "]" << endl; // Output: [1, 4]
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
, where N is the number of nodes in the BST- Because the code performs an in-order traversal of the BST, which requires O(N) time.
- Space Complexity:
O(N)
, since the code stores all the node values in a list.