📜  完美二进制搜索树中的Kth个最小元素

📅  最后修改于: 2021-04-29 18:13:53             🧑  作者: Mango

给定具有N个节点和整数KPerfect 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个最小元素
  • Perfect BST的右侧子树将始终包含第R个最小元素 如果
    • K> location(median(N))= M,在这种情况下, K – location(median(N))= R是右子树中第R个最小的元素。这是因为右子树中的第R个最小元素大于第M个最小元素,而左子树中的每个元素都小于第M个最小元素,而第R个最小元素大于所有它们。当至少M个较小的可能性可以忽略时,可以将R视为新数字。第r 最小元素是重复出现在正确的子树中的第K个最小元素(但请记住,R != K!)。
  • 如果Klocation(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))