📜  在BST中查找第k个最小元素(BST中的订单统计信息)

📅  最后修改于: 2021-05-24 23:45:41             🧑  作者: Mango

给定二叉搜索树的根,并输入K,在BST中找到第K个最小元素。
例如,在下面的BST中,如果k = 3,则输出应为10,如果k = 5,则输出应为14。

方法1:使用有序遍历(O(n)时间和O(h)辅助空间)
BST的有序遍历以递增顺序遍历节点。因此,想法是遍历Inorder中的树。遍历时,请跟踪访问的节点数。如果计数变为k,则打印该节点。

C++
// A simple inorder traversal based C++ program
// to find k-th smallest element in a BST.
#include 
using namespace std;
 
// A BST node
struct Node {
    int data;
    Node *left, *right;
    Node(int x)
    {
        data = x;
        left = right = NULL;
    }
};
 
// Recursive function to insert an key into BST
Node* insert(Node* root, int x)
{
    if (root == NULL)
        return new Node(x);
    if (x < root->data)
        root->left = insert(root->left, x);
    else if (x > root->data)
        root->right = insert(root->right, x);
    return root;
}
 
// Function to find k'th largest element in BST
// Here count denotes the number of nodes processed so far
Node* kthSmallest(Node* root, int& k)
{
    // base case
    if (root == NULL)
        return NULL;
 
    // search in left subtree
    Node* left = kthSmallest(root->left, k);
 
    // if k'th smallest is found in left subtree, return it
    if (left != NULL)
        return left;
 
    // if current element is k'th smallest, return it
    k--;
    if (k == 0)
        return root;
 
    // else search in right subtree
    return kthSmallest(root->right, k);
}
 
// Function to find k'th largest element in BST
void printKthSmallest(Node* root, int k)
{
    // maintain index to count number of nodes processed so far
    int count = 0;
    Node* res = kthSmallest(root, k);
    if (res == NULL)
        cout << "There are less than k nodes in the BST";
    else
        cout << "K-th Smallest Element is " << res->data;
}
 
// main function
int main()
{
    Node* root = NULL;
    int keys[] = { 20, 8, 22, 4, 12, 10, 14 };
 
    for (int x : keys)
        root = insert(root, x);
 
    int k = 3;
    printKthSmallest(root, k);
    return 0;
}


Java
// A simple inorder traversal based Java program
// to find k-th smallest element in a BST.
 
import java.io.*;
// A BST node
class Node {
    int data;
    Node left, right;
    Node(int x)
    {
        data = x;
        left = right = null;
    }
}
 
class GFG {
    
    static int count = 0;
    // Recursive function to insert an key into BST
    public static Node insert(Node root, int x)
    {
        if (root == null)
            return new Node(x);
        if (x < root.data)
            root.left = insert(root.left, x);
        else if (x > root.data)
            root.right = insert(root.right, x);
        return root;
    }
      
    // Function to find k'th largest element in BST
    // Here count denotes the number
    // of nodes processed so far
    public static Node kthSmallest(Node root, int k)
    {
        // base case
        if (root == null)
            return null;
      
        // search in left subtree
        Node left = kthSmallest(root.left, k);
      
        // if k'th smallest is found in left subtree, return it
        if (left != null)
            return left;
      
        // if current element is k'th smallest, return it
        count++;
        if (count == k)
            return root;
      
        // else search in right subtree
        return kthSmallest(root.right, k);
    }
      
    // Function to find k'th largest element in BST
    public static void printKthSmallest(Node root, int k)
    {
        // maintain an index to count number of
        // nodes processed so far
        count = 0;
         
        Node res = kthSmallest(root, k);
        if (res == null)
            System.out.println("There are less "
                        + "than k nodes in the BST");
        else
            System.out.println("K-th Smallest"
                    + " Element is " + res.data);
    }
         
    public static void main (String[] args) {
         
        Node root = null;
        int keys[] = { 20, 8, 22, 4, 12, 10, 14 };
      
        for (int x : keys)
            root = insert(root, x);
         
        int k = 3;
        printKthSmallest(root, k);
         
         
    }
}


Python3
# A simple inorder traversal based Python3
# program to find k-th smallest element
# in a BST.
 
# A BST node
class Node:
     
    def __init__(self, key):
         
        self.data = key
        self.left = None
        self.right = None
 
# Recursive function to insert an key into BST
def insert(root, x):
     
    if (root == None):
        return Node(x)
    if (x < root.data):
        root.left = insert(root.left, x)
    elif (x > root.data):
        root.right = insert(root.right, x)
    return root
 
# Function to find k'th largest element
# in BST. Here count denotes the number
# of nodes processed so far
def kthSmallest(root):
     
    global k
     
    # Base case
    if (root == None):
        return None
 
    # Search in left subtree
    left = kthSmallest(root.left)
 
    # If k'th smallest is found in
    # left subtree, return it
    if (left != None):
        return left
         
    # If current element is k'th
    # smallest, return it
    k -= 1
    if (k == 0):
        return root
 
    # Else search in right subtree
    return kthSmallest(root.right)
 
# Function to find k'th largest element in BST
def printKthSmallest(root):
     
    # Maintain index to count number
    # of nodes processed so far
    count = 0
    res = kthSmallest(root)
     
    if (res == None):
        print("There are less than k nodes in the BST")
    else:
        print("K-th Smallest Element is ", res.data)
 
# Driver code
if __name__ == '__main__':
     
    root = None
    keys = [ 20, 8, 22, 4, 12, 10, 14 ]
 
    for x in keys:
        root = insert(root, x)
 
    k = 3
     
    printKthSmallest(root)
 
# This code is contributed by mohit kumar 29


C#
// A simple inorder traversal
// based C# program to find
// k-th smallest element in a BST.
using System;
 
// A BST node
class Node{
 
public int data;
public Node left, right;
public Node(int x)
{
  data = x;
  left = right = null;
}
}
 
class GFG{
    
static int count = 0;
 
// Recursive function to 
// insert an key into BST
public static Node insert(Node root,
                          int x)
{
  if (root == null)
    return new Node(x);
  if (x < root.data)
    root.left = insert(root.left, x);
  else if (x > root.data)
    root.right = insert(root.right, x);
  return root;
}
      
// Function to find k'th largest
// element in BST. Here count
// denotes the number of nodes
// processed so far
public static Node kthSmallest(Node root,
                               int k)
{
  // base case
  if (root == null)
    return null;
 
  // search in left subtree
  Node left = kthSmallest(root.left, k);
 
  // if k'th smallest is found
  // in left subtree, return it
  if (left != null)
    return left;
 
  // if current element is
  // k'th smallest, return it
  count++;
  if (count == k)
    return root;
 
  // else search in right subtree
  return kthSmallest(root.right, k);
}
 
// Function to find k'th largest
// element in BST
public static void printKthSmallest(Node root,
                                    int k)
{
  // Maintain an index to
  // count number of nodes
  // processed so far
  count = 0;
 
  Node res = kthSmallest(root, k);
   
  if (res == null)
    Console.WriteLine("There are less " +
                      "than k nodes in the BST");
  else
    Console.WriteLine("K-th Smallest" +
                      " Element is " + res.data);
}
 
// Driver code
public static void Main(String[] args)
{
 
  Node root = null;
  int []keys = {20, 8, 22, 4,
                12, 10, 14};
   
  foreach (int x in keys)
    root = insert(root, x);
 
  int k = 3;
  printKthSmallest(root, k);
}
}
 
// This code is contributed by gauravrajput1


Javascript


C++
// A simple inorder traversal based C++ program
// to find k-th smallest element in a BST.
#include 
using namespace std;
 
// A BST node
struct Node {
    int data;
    Node *left, *right;
    int lCount;
    Node(int x)
    {
        data = x;
        left = right = NULL;
        lCount = 0;
    }
};
 
// Recursive function to insert an key into BST
Node* insert(Node* root, int x)
{
    if (root == NULL)
        return new Node(x);
 
    // If a node is inserted in left subtree, then
    // lCount of this node is increased. For simplicity,
    // we are assuming that all keys (tried to be
    // inserted) are distinct.
    if (x < root->data) {
        root->left = insert(root->left, x);
        root->lCount++;
    }
 
    else if (x > root->data)
        root->right = insert(root->right, x);
    return root;
}
 
// Function to find k'th largest element in BST
// Here count denotes the number of nodes processed so far
Node* kthSmallest(Node* root, int k)
{
    // base case
    if (root == NULL)
        return NULL;
 
    int count = root->lCount + 1;
    if (count == k)
        return root;
 
    if (count > k)
        return kthSmallest(root->left, k);
 
    // else search in right subtree
    return kthSmallest(root->right, k - count);
}
 
// main function
int main()
{
    Node* root = NULL;
    int keys[] = { 20, 8, 22, 4, 12, 10, 14 };
 
    for (int x : keys)
        root = insert(root, x);
 
    int k = 4;
    Node* res = kthSmallest(root, k);
    if (res == NULL)
        cout << "There are less than k nodes in the BST";
    else
        cout << "K-th Smallest Element is " << res->data;
    return 0;
}


Java
// A simple inorder traversal based Java program
// to find k-th smallest element in a BST.
import java.io.*;
import java.util.*;
 
// A BST node
class Node {
    int data;
    Node left, right;
    int lCount;
    Node(int x)
    {
        data = x;
        left = right = null;
        lCount = 0;
    }
}
 
 
class Gfg
{
    // Recursive function to insert an key into BST
    public static Node insert(Node root, int x)
    {
        if (root == null)
            return new Node(x);
     
        // If a node is inserted in left subtree, then
        // lCount of this node is increased. For simplicity,
        // we are assuming that all keys (tried to be
        // inserted) are distinct.
        if (x < root.data) {
            root.left = insert(root.left, x);
            root.lCount++;
        }
     
        else if (x > root.data)
            root.right = insert(root.right, x);
        return root;
    }
     
    // Function to find k'th largest element in BST
    // Here count denotes the number of
    // nodes processed so far
    public static Node kthSmallest(Node root, int k)
    {
        // base case
        if (root == null)
            return null;
     
        int count = root.lCount + 1;
        if (count == k)
            return root;
     
        if (count > k)
            return kthSmallest(root.left, k);
     
        // else search in right subtree
        return kthSmallest(root.right, k - count);
    }
     
    // main function
    public static void main(String args[])
    {
        Node root = null;
        int keys[] = { 20, 8, 22, 4, 12, 10, 14 };
     
        for (int x : keys)
            root = insert(root, x);
     
        int k = 4;
        Node res = kthSmallest(root, k);
        if (res == null)
            System.out.println("There are less "
                           + "than k nodes in the BST");
        else
            System.out.println("K-th Smallest"
                    + " Element is " + res.data);
    }
}


Python3
# A simple inorder traversal based Python3
# program to find k-th smallest element in a BST.
 
# A BST node
class newNode:
     
    def __init__(self, x):
         
        self.data = x
        self.left = None
        self.right = None
        self.lCount = 0
 
# Recursive function to insert
# an key into BST
def insert(root, x):
     
    if (root == None):
        return newNode(x)
 
    # If a node is inserted in left subtree,
    # then lCount of this node is increased.
    # For simplicity, we are assuming that
    # all keys (tried to be inserted) are
    # distinct.
    if (x < root.data):
        root.left = insert(root.left, x)
        root.lCount += 1
 
    elif (x > root.data):
        root.right = insert(root.right, x);
         
    return root
 
# Function to find k'th largest element
# in BST. Here count denotes the number
# of nodes processed so far
def kthSmallest(root, k):
     
    # Base case
    if (root == None):
        return None
         
    count = root.lCount + 1
     
    if (count == k):
        return root
 
    if (count > k):
        return kthSmallest(root.left, k)
 
    # Else search in right subtree
    return kthSmallest(root.right, k - count)
 
# Driver code
if __name__ == '__main__':
     
    root = None
    keys = [ 20, 8, 22, 4, 12, 10, 14 ]
 
    for x in keys:
        root = insert(root, x)
 
    k = 4
    res = kthSmallest(root, k)
     
    if (res == None):
        print("There are less than k nodes in the BST")
    else:
        print("K-th Smallest Element is", res.data)
         
# This code is contributed by bgangwar59


C#
// A simple inorder traversal based C# program
// to find k-th smallest element in a BST.
using System;
 
// A BST node
public class Node
{
    public int data;
    public Node left, right;
    public int lCount;
     
    public Node(int x)
    {
        data = x;
        left = right = null;
        lCount = 0;
    }
}
 
class GFG{
     
// Recursive function to insert an key into BST
public static Node insert(Node root, int x)
{
    if (root == null)
        return new Node(x);
         
    // If a node is inserted in left subtree,
    // then lCount of this node is increased.
    // For simplicity, we are assuming that
    // all keys (tried to be inserted) are
    // distinct.
    if (x < root.data)
    {
        root.left = insert(root.left, x);
        root.lCount++;
    }
 
    else if (x > root.data)
        root.right = insert(root.right, x);
         
    return root;
}
 
// Function to find k'th largest element
// in BST. Here count denotes the number
// of nodes processed so far
public static Node kthSmallest(Node root, int k)
{
     
    // Base case
    if (root == null)
        return null;
 
    int count = root.lCount + 1;
    if (count == k)
        return root;
 
    if (count > k)
        return kthSmallest(root.left, k);
 
    // Else search in right subtree
    return kthSmallest(root.right, k - count);
}
 
// Driver Code
public static void Main(String[] args)
{
    Node root = null;
    int[] keys = { 20, 8, 22, 4, 12, 10, 14 };
 
    foreach(int x in keys)
        root = insert(root, x);
 
    int k = 4;
    Node res = kthSmallest(root, k);
     
    if (res == null)
        Console.WriteLine("There are less " +
                          "than k nodes in the BST");
    else
        Console.WriteLine("K-th Smallest" +
                          " Element is " + res.data);
}
}
 
// This code is contributed by aashish1995


输出:
K-th Smallest Element is 10

我们可以使用Morris Traversal优化空间。有关详细信息,请使用O(1)额外空间引用BST中的第K个最小元素。

方法2:增强树数据结构(O(h)时间复杂度和O(h)辅助空间)
这个想法是维持每个节点的等级。在构建树时,我们可以跟踪每个节点左子树中的元素。由于我们需要第K个最小的元素,因此我们可以维护每个节点中左子树的元素数量。
假设根在其左子树中具有“ lCount”个节点。如果K = lCount + 1,则根是第K个节点。如果K lCount + 1,我们继续在右子树中搜索第(K – lCount – 1)个最小元素。请注意,我们仅需要左侧子树中的元素计数。

C++

// A simple inorder traversal based C++ program
// to find k-th smallest element in a BST.
#include 
using namespace std;
 
// A BST node
struct Node {
    int data;
    Node *left, *right;
    int lCount;
    Node(int x)
    {
        data = x;
        left = right = NULL;
        lCount = 0;
    }
};
 
// Recursive function to insert an key into BST
Node* insert(Node* root, int x)
{
    if (root == NULL)
        return new Node(x);
 
    // If a node is inserted in left subtree, then
    // lCount of this node is increased. For simplicity,
    // we are assuming that all keys (tried to be
    // inserted) are distinct.
    if (x < root->data) {
        root->left = insert(root->left, x);
        root->lCount++;
    }
 
    else if (x > root->data)
        root->right = insert(root->right, x);
    return root;
}
 
// Function to find k'th largest element in BST
// Here count denotes the number of nodes processed so far
Node* kthSmallest(Node* root, int k)
{
    // base case
    if (root == NULL)
        return NULL;
 
    int count = root->lCount + 1;
    if (count == k)
        return root;
 
    if (count > k)
        return kthSmallest(root->left, k);
 
    // else search in right subtree
    return kthSmallest(root->right, k - count);
}
 
// main function
int main()
{
    Node* root = NULL;
    int keys[] = { 20, 8, 22, 4, 12, 10, 14 };
 
    for (int x : keys)
        root = insert(root, x);
 
    int k = 4;
    Node* res = kthSmallest(root, k);
    if (res == NULL)
        cout << "There are less than k nodes in the BST";
    else
        cout << "K-th Smallest Element is " << res->data;
    return 0;
}

Java

// A simple inorder traversal based Java program
// to find k-th smallest element in a BST.
import java.io.*;
import java.util.*;
 
// A BST node
class Node {
    int data;
    Node left, right;
    int lCount;
    Node(int x)
    {
        data = x;
        left = right = null;
        lCount = 0;
    }
}
 
 
class Gfg
{
    // Recursive function to insert an key into BST
    public static Node insert(Node root, int x)
    {
        if (root == null)
            return new Node(x);
     
        // If a node is inserted in left subtree, then
        // lCount of this node is increased. For simplicity,
        // we are assuming that all keys (tried to be
        // inserted) are distinct.
        if (x < root.data) {
            root.left = insert(root.left, x);
            root.lCount++;
        }
     
        else if (x > root.data)
            root.right = insert(root.right, x);
        return root;
    }
     
    // Function to find k'th largest element in BST
    // Here count denotes the number of
    // nodes processed so far
    public static Node kthSmallest(Node root, int k)
    {
        // base case
        if (root == null)
            return null;
     
        int count = root.lCount + 1;
        if (count == k)
            return root;
     
        if (count > k)
            return kthSmallest(root.left, k);
     
        // else search in right subtree
        return kthSmallest(root.right, k - count);
    }
     
    // main function
    public static void main(String args[])
    {
        Node root = null;
        int keys[] = { 20, 8, 22, 4, 12, 10, 14 };
     
        for (int x : keys)
            root = insert(root, x);
     
        int k = 4;
        Node res = kthSmallest(root, k);
        if (res == null)
            System.out.println("There are less "
                           + "than k nodes in the BST");
        else
            System.out.println("K-th Smallest"
                    + " Element is " + res.data);
    }
}

Python3

# A simple inorder traversal based Python3
# program to find k-th smallest element in a BST.
 
# A BST node
class newNode:
     
    def __init__(self, x):
         
        self.data = x
        self.left = None
        self.right = None
        self.lCount = 0
 
# Recursive function to insert
# an key into BST
def insert(root, x):
     
    if (root == None):
        return newNode(x)
 
    # If a node is inserted in left subtree,
    # then lCount of this node is increased.
    # For simplicity, we are assuming that
    # all keys (tried to be inserted) are
    # distinct.
    if (x < root.data):
        root.left = insert(root.left, x)
        root.lCount += 1
 
    elif (x > root.data):
        root.right = insert(root.right, x);
         
    return root
 
# Function to find k'th largest element
# in BST. Here count denotes the number
# of nodes processed so far
def kthSmallest(root, k):
     
    # Base case
    if (root == None):
        return None
         
    count = root.lCount + 1
     
    if (count == k):
        return root
 
    if (count > k):
        return kthSmallest(root.left, k)
 
    # Else search in right subtree
    return kthSmallest(root.right, k - count)
 
# Driver code
if __name__ == '__main__':
     
    root = None
    keys = [ 20, 8, 22, 4, 12, 10, 14 ]
 
    for x in keys:
        root = insert(root, x)
 
    k = 4
    res = kthSmallest(root, k)
     
    if (res == None):
        print("There are less than k nodes in the BST")
    else:
        print("K-th Smallest Element is", res.data)
         
# This code is contributed by bgangwar59

C#

// A simple inorder traversal based C# program
// to find k-th smallest element in a BST.
using System;
 
// A BST node
public class Node
{
    public int data;
    public Node left, right;
    public int lCount;
     
    public Node(int x)
    {
        data = x;
        left = right = null;
        lCount = 0;
    }
}
 
class GFG{
     
// Recursive function to insert an key into BST
public static Node insert(Node root, int x)
{
    if (root == null)
        return new Node(x);
         
    // If a node is inserted in left subtree,
    // then lCount of this node is increased.
    // For simplicity, we are assuming that
    // all keys (tried to be inserted) are
    // distinct.
    if (x < root.data)
    {
        root.left = insert(root.left, x);
        root.lCount++;
    }
 
    else if (x > root.data)
        root.right = insert(root.right, x);
         
    return root;
}
 
// Function to find k'th largest element
// in BST. Here count denotes the number
// of nodes processed so far
public static Node kthSmallest(Node root, int k)
{
     
    // Base case
    if (root == null)
        return null;
 
    int count = root.lCount + 1;
    if (count == k)
        return root;
 
    if (count > k)
        return kthSmallest(root.left, k);
 
    // Else search in right subtree
    return kthSmallest(root.right, k - count);
}
 
// Driver Code
public static void Main(String[] args)
{
    Node root = null;
    int[] keys = { 20, 8, 22, 4, 12, 10, 14 };
 
    foreach(int x in keys)
        root = insert(root, x);
 
    int k = 4;
    Node res = kthSmallest(root, k);
     
    if (res == null)
        Console.WriteLine("There are less " +
                          "than k nodes in the BST");
    else
        Console.WriteLine("K-th Smallest" +
                          " Element is " + res.data);
}
}
 
// This code is contributed by aashish1995
输出:
K-th Smallest Element is 12

时间复杂度: O(h)其中h是树的高度。