给定具有N个节点和整数K的Perfect BST ,任务是找到树中存在的第K个最小元素。
例子:
Input:
K = 3, N = 15
50
/ \
30 70
/ \ / \
20 40 60 80
/\ /\ /\ / \
14 25 35 45 55 65 75 85
Output: 25
Explanation:
The 3rd smallest element
in the given BST is 25
Input:
K = 9, N = 15
50
/ \
30 70
/ \ / \
20 40 60 80
/\ /\ /\ / \
14 25 35 45 55 65 75 85
Output: 55
Explanation:
The 9th smallest element
in the given BST is 55
天真的方法:在完美的BST中进行有序遍历,例如morris遍历或递归解决方案,该遍历遍历每个节点并返回第k个访问键。完成任务需要O(N)时间复杂度。
高效方法:
由于给定的BST是完美的并且整个树的节点数是已知的,因此可以将解决该问题的计算复杂度降低为log(N) 。请按照以下步骤解决问题:
- 在理想的BST树(N)中,| N |在理想的二叉树中总是奇数,在任何理想的BST中,中位数的位置是floor(| N | / 2)+ 1。
- 计算中的节点数 通过将总节点除以地板(| N | / 2)来划分每个子树。
- 如果满足以下条件,则Perfect BST的左子树将始终包含第K个最小元素:
- K
这是因为第M个最小元素将始终大于第K个最小元素,并且右子树中的每个元素都将大于第M个最小元素
- K
- Perfect BST的右侧子树将始终包含第R个最小元素 如果:
- K> location(median(N))= M,在这种情况下, K – location(median(N))= R是右子树中第R个最小的元素。这是因为右子树中的第R个最小元素大于第M个最小元素,而左子树中的每个元素都小于第M个最小元素,而第R个最小元素大于所有它们。当至少M个较小的可能性可以忽略时,可以将R视为新数字。第r个 最小元素是重复出现在正确的子树中的第K个最小元素(但请记住,R != K!)。
- 如果K为location(median(T)),则该节点在完美BST中包含第K个最小元素。
下面是上述方法的实现:
C++
// C++ program to find K-th
// smallest element in a
// perfect BST
#include
using namespace std;
// A BST node
struct Node
{
int key;
Node *left, *right;
};
// A utility function to
// create a new BST node
Node* newNode(int item)
{
Node* temp = new Node;
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
// A utility function to insert a
// new node with given key in BST
Node* insert(Node* node, int key)
{
// If the tree is empty
if (node == NULL)
return newNode(key);
// Recur down the left
// subtree for smaller values
if (key < node->key)
node->left = insert(node->left, key);
// Recur down the right
// subtree for smaller values
else if (key > node->key)
node->right = insert(node->right, key);
// Return the (unchanged) node pointer
return node;
}
// FUnction to find Kth Smallest
// element in a perfect BST
bool KSmallestPerfectBST(Node* root, int k,
int treeSize,
int& kth_smallest)
{
if (root == NULL)
return false;
// Find the median
// (division operation is floored)
int median_loc = (treeSize / 2) + 1;
// If the element is at
// the median
if (k == median_loc)
{
kth_smallest = root->key;
return true;
}
// calculate the number of nodes in the
// right and left sub-trees
// (division operation is floored)
int newTreeSize = treeSize / 2;
// If median is located higher
if (k < median_loc)
{
return KSmallestPerfectBST(
root->left, k,
newTreeSize, kth_smallest);
}
// If median is located lower
int newK = k - median_loc;
return KSmallestPerfectBST(root->right, newK,
newTreeSize,
kth_smallest);
}
// Driver Code
int main()
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80
/\ /\ /\ / \
14 25 35 45 55 65 75 85
*/
Node* root = NULL;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
insert(root, 14);
insert(root, 25);
insert(root, 35);
insert(root, 45);
insert(root, 55);
insert(root, 65);
insert(root, 75);
insert(root, 85);
int n = 15, k = 5;
int ans = -1;
// Function call
if (KSmallestPerfectBST(root, k, n, ans)) {
cout << ans << " ";
}
return 0;
}
Java
// Java program to find K-th
// smallest element in a
// perfect BST
import java.util.*;
class GFG{
// A BST node
static class Node
{
int key;
Node left, right;
};
static int kth_smallest;
// A utility function to
// create a new BST node
public static Node newNode(int item)
{
Node temp = new Node();
temp.key = item;
temp.left = temp.right = null;
return temp;
}
// A utility function to insert a
// new node with given key in BST
static Node insert(Node node, int key)
{
// If the tree is empty
if (node == null)
return newNode(key);
// Recur down the left
// subtree for smaller values
if (key < node.key)
node.left = insert(node.left, key);
// Recur down the right
// subtree for smaller values
else if (key > node.key)
node.right = insert(node.right, key);
// Return the (unchanged) node pointer
return node;
}
// FUnction to find Kth Smallest
// element in a perfect BST
static boolean KSmallestPerfectBST(Node root, int k,
int treeSize)
{
if (root == null)
return false;
// Find the median
// (division operation is floored)
int median_loc = (treeSize / 2) + 1;
// If the element is at
// the median
if (k == median_loc)
{
kth_smallest = root.key;
return true;
}
// calculate the number of nodes in the
// right and left sub-trees
// (division operation is floored)
int newTreeSize = treeSize / 2;
// If median is located higher
if (k < median_loc)
{
return KSmallestPerfectBST(
root.left, k,
newTreeSize);
}
// If median is located lower
int newK = k - median_loc;
return KSmallestPerfectBST(root.right, newK,
newTreeSize);
}
// Driver Code
public static void main(String[] args)
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80
/\ /\ /\ / \
14 25 35 45 55 65 75 85
*/
Node root = null;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
insert(root, 14);
insert(root, 25);
insert(root, 35);
insert(root, 45);
insert(root, 55);
insert(root, 65);
insert(root, 75);
insert(root, 85);
int n = 15, k = 5;
// Function call
if (KSmallestPerfectBST(root, k, n))
{
System.out.print(kth_smallest + " ");
}
}
}
// This code is contributed by Amit Katiyar
Python3
# Python3 program to find K-th
# smallest element in a perfect BST
kth_smallest = 0
# A BST node
class newNode:
def __init__(self, item):
self.key = item
self.left = None
self.right = None
# A utility function to insert a
# new node with given key in BST
def insert(node, key):
# If the tree is empty
if (node == None):
return newNode(key)
# Recur down the left
# subtree for smaller values
if (key < node.key):
node.left = insert(node.left, key)
# Recur down the right
# subtree for smaller values
elif(key > node.key):
node.right = insert(node.right, key)
# Return the (unchanged) node pointer
return node
# FUnction to find Kth Smallest
# element in a perfect BST
def KSmallestPerfectBST(root, k, treeSize):
global kth_smallest
if (root == None):
return False
# Find the median
# (division operation is floored)
median_loc = (treeSize // 2) + 1
# If the element is at
# the median
if (k == median_loc):
kth_smallest = root.key
return True
# Calculate the number of nodes in
# the right and left sub-trees
# (division operation is floored)
newTreeSize = treeSize // 2
# If median is located higher
if (k < median_loc):
return KSmallestPerfectBST(root.left,
k, newTreeSize)
# If median is located lower
newK = k - median_loc
return KSmallestPerfectBST(root.right, newK,
newTreeSize)
# Driver Code
if __name__ == '__main__':
''' Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80
/\ /\ /\ / \
14 25 35 45 55 65 75 85
'''
root = None
root = insert(root, 50)
insert(root, 30)
insert(root, 20)
insert(root, 40)
insert(root, 70)
insert(root, 60)
insert(root, 80)
insert(root, 14)
insert(root, 25)
insert(root, 35)
insert(root, 45)
insert(root, 55)
insert(root, 65)
insert(root, 75)
insert(root, 85)
n = 15
k = 5
# Function call
if (KSmallestPerfectBST(root, k, n)):
print(kth_smallest, end = " ")
# This code is contributed by ipg2016107
C#
// C# program to find K-th
// smallest element in a
// perfect BST
using System;
class GFG{
// A BST node
public class Node
{
public int key;
public Node left,
right;
};
static int kth_smallest;
// A utility function to
// create a new BST node
public static Node newNode(int item)
{
Node temp = new Node();
temp.key = item;
temp.left = temp.right = null;
return temp;
}
// A utility function to
// insert a new node with
// given key in BST
static Node insert(Node node,
int key)
{
// If the tree is empty
if (node == null)
return newNode(key);
// Recur down the left
// subtree for smaller values
if (key < node.key)
node.left = insert(node.left,
key);
// Recur down the right
// subtree for smaller values
else if (key > node.key)
node.right = insert(node.right,
key);
// Return the (unchanged)
// node pointer
return node;
}
// Function to find Kth Smallest
// element in a perfect BST
static bool KSmallestPerfectBST(Node root, int k,
int treeSize)
{
if (root == null)
return false;
// Find the median
// (division operation is floored)
int median_loc = (treeSize / 2) + 1;
// If the element is at
// the median
if (k == median_loc)
{
kth_smallest = root.key;
return true;
}
// calculate the number of nodes
// in the right and left sub-trees
// (division operation is floored)
int newTreeSize = treeSize / 2;
// If median is located higher
if (k < median_loc)
{
return KSmallestPerfectBST(root.left, k,
newTreeSize);
}
// If median is located lower
int newK = k - median_loc;
return KSmallestPerfectBST(root.right, newK,
newTreeSize);
}
// Driver Code
public static void Main(String[] args)
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80
/\ /\ /\ / \
14 25 35 45 55 65 75 85
*/
Node root = null;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
insert(root, 14);
insert(root, 25);
insert(root, 35);
insert(root, 45);
insert(root, 55);
insert(root, 65);
insert(root, 75);
insert(root, 85);
int n = 15, k = 5;
// Function call
if (KSmallestPerfectBST(root,
k, n))
{
Console.Write(kth_smallest + " ");
}
}
}
// This code is contributed by Rajput-Ji
输出
35
时间复杂度: O(Log(N))
辅助空间: O(Log(N))