Tìm phần tử nhỏ nhất thứ k trong cây tìm kiếm nhị phân theo cách Tối ưu


112

Tôi cần tìm phần tử nhỏ nhất thứ k trong cây tìm kiếm nhị phân mà không sử dụng bất kỳ biến tĩnh / toàn cục nào. Làm thế nào để đạt được nó một cách hiệu quả? Giải pháp mà tôi có trong đầu là thực hiện phép toán trong O (n), trường hợp xấu nhất vì tôi đang lên kế hoạch thực hiện một chuyến đi ngang qua không gian của toàn bộ cây. Nhưng trong sâu thẳm, tôi cảm thấy rằng tôi không sử dụng tài sản BST ở đây. Giải pháp giả định của tôi có đúng không hay có giải pháp nào tốt hơn không?


7
Cây có cân đối không?
kennytm

Nó không thể. Nhưng nếu nó đã được cân bằng, có cách nào tối ưu không?
bragboy

1
Nếu bạn thực hiện tìm kiếm trên "Thống kê đơn hàng", bạn sẽ tìm thấy những gì bạn cần.
RAL

Tôi cảm thấy hầu hết các câu trả lời dưới đây, trong khi đúng lại gian lận ở chỗ họ đang sử dụng một biến toàn cục của một số loại (cho dù đó là tham chiếu đến một số nguyên hay một biến được giảm dần và trả về). Nếu hoàn toàn không ai trong số những người được cho phép, tôi sẽ sử dụng đệ quy mà không cần bất kỳ tài liệu tham khảo được thông qua tại.
Henley Chiu

Câu trả lời:


170

Đây chỉ là một phác thảo của ý tưởng:

Trong BST, cây con bên trái của nút Tchỉ chứa các phần tử nhỏ hơn giá trị được lưu trữ trong đó T. Nếu knhỏ hơn số phần tử trong cây con bên trái thì kphần tử nhỏ nhất thứ hai phải thuộc cây con bên trái. Ngược lại, nếu klớn hơn, thì kphần tử nhỏ nhất thứ ở trong cây con bên phải.

Chúng ta có thể tăng cường BST để mỗi nút trong đó lưu trữ số phần tử trong cây con bên trái của nó (giả sử rằng cây con bên trái của một nút nhất định bao gồm nút đó). Với phần thông tin này, thật đơn giản để duyệt qua cây bằng cách liên tục hỏi số phần tử trong cây con bên trái, để quyết định xem nên thực hiện đệ quy vào cây con bên trái hay bên phải.

Bây giờ, giả sử chúng ta đang ở nút T:

  1. Nếu k == num_elements (cây con bên trái của T) , thì câu trả lời chúng ta đang tìm là giá trị trong nút T.
  2. Nếu k> num_elements (cây con bên trái của T) , thì rõ ràng chúng ta có thể bỏ qua cây con bên trái, bởi vì những phần tử đó cũng sẽ nhỏ hơn knhỏ nhất thứ. Vì vậy, chúng ta rút k - num_elements(left subtree of T)gọn vấn đề thành tìm phần tử nhỏ nhất của cây con bên phải.
  3. Nếu k <num_elements (cây con bên trái của T) , thì phần tử knhỏ nhất thứ ở đâu đó trong cây con bên trái, vì vậy chúng ta rút kgọn bài toán thành tìm phần tử nhỏ nhất thứ ba trong cây con bên trái.

Phân tích độ phức tạp:

Điều này cần O(depth of node)thời gian, O(log n)trong trường hợp xấu nhất là đối với một BST cân bằng, hoặc O(log n)trung bình đối với một BST ngẫu nhiên.

Một BST yêu cầu O(n)lưu trữ và cần một BST khác O(n)để lưu trữ thông tin về số lượng phần tử. Tất cả các thao tác BST cần có O(depth of node)thời gian và cần O(depth of node)thêm thời gian để duy trì thông tin "số phần tử" cho việc chèn, xóa hoặc xoay các nút. Do đó, việc lưu trữ thông tin về số lượng phần tử trong cây con bên trái giữ độ phức tạp về không gian và thời gian của BST.


59
Để tìm mục nhỏ nhất thứ N, bạn chỉ cần lưu trữ kích thước của cây con bên trái. Bạn sẽ sử dụng kích thước của cây con bên phải ii nếu bạn cũng muốn có thể tìm thấy mục lớn thứ N. Trên thực tế, bạn có thể làm điều đó ít tốn kém hơn: lưu trữ tổng kích thước của cây trong gốc và kích thước của cây phụ bên trái. Khi bạn cần kích thước của cây con bên phải, bạn có thể trừ kích thước của cây bên trái khỏi tổng kích thước.
Jerry Coffin

37
Một BST bổ sung như vậy được gọi là 'cây thống kê đơn hàng'.
Daniel

10
@Ivlad: ở bước 2: Tôi nghĩ "k - num_elements" phải là "k - num_elements -1", vì bạn cũng phải bao gồm phần tử gốc.
understack

1
@understack - không phải nếu bạn cho rằng gốc là một phần của cây con.
IVlad

16
Nếu cây không chứa trường chứa "số phần tử trong cây con bên trái và bên phải của nó" thì phương thức sẽ kết thúc là BigO (n) vì bạn sẽ cần đi qua cây con bên phải hoặc bên trái tại mỗi nút để tính chỉ số k của nút hiện tại.
Robert S. Barnes,

68

Một giải pháp đơn giản hơn sẽ là thực hiện duyệt qua inorder và theo dõi phần tử hiện đang được in (mà không cần in). Khi chúng ta đạt đến k, in phần tử và bỏ qua phần còn lại của quá trình duyệt cây.

void findK(Node* p, int* k) {
  if(!p || k < 0) return;
  findK(p->left, k);
  --k;
  if(k == 0) { 
    print p->data;
    return;  
  } 
  findK(p->right, k); 
}

1
+1: Ý tưởng là đúng hướng, nhưng một số đầu lỏng lẻo có thể cần được thắt lại; xem stackoverflow.com/a/23069077/278326
Arun

1
Tôi thích giải pháp này, vì BST đã được đặt hàng, nên chỉ cần một lượt duyệt là đủ.
Merlin

3
Nếu n là gần với tổng số nút trong cây này, thuật toán của bạn sẽ mất O (n) thời gian để kết thúc, mà có hại cho các lựa chọn câu trả lời-O (log n)
Spark8006

13
public int ReturnKthSmallestElement1(int k)
    {
        Node node = Root;

        int count = k;

        int sizeOfLeftSubtree = 0;

        while(node != null)
        {

            sizeOfLeftSubtree = node.SizeOfLeftSubtree();

            if (sizeOfLeftSubtree + 1 == count)
                return node.Value;
            else if (sizeOfLeftSubtree < count)
            {
                node = node.Right;
                count -= sizeOfLeftSubtree+1;
            }
            else
            {
                node = node.Left;
            }
        }

        return -1;
    }

đây là cách triển khai của tôi trong C # dựa trên thuật toán ở trên, tôi chỉ nghĩ rằng tôi sẽ đăng nó để mọi người có thể hiểu rõ hơn nó hoạt động với tôi

cảm ơn IVlad


11

Một giải pháp đơn giản hơn sẽ là thực hiện một trình duyệt inorder và theo dõi phần tử hiện đang được in bằng bộ đếm k. Khi chúng ta đạt đến k, in phần tử. Thời gian chạy là O (n). Hãy nhớ rằng kiểu trả về của hàm không thể bị vô hiệu, nó phải trả về giá trị cập nhật của nó là k sau mỗi lần gọi đệ quy. Giải pháp tốt hơn cho điều này sẽ là một BST tăng cường với giá trị vị trí được sắp xếp tại mỗi nút.

public static int kthSmallest (Node pivot, int k){
    if(pivot == null )
        return k;   
    k = kthSmallest(pivot.left, k);
    k--;
    if(k == 0){
        System.out.println(pivot.value);
    }
    k = kthSmallest(pivot.right, k);
    return k;
}

Tôi đoán giải pháp của bạn tốt hơn về độ phức tạp của không gian so với BST tăng cường.
zach

Việc tìm kiếm không dừng lại ngay cả khi tìm thấy phần tử nhỏ nhất thứ k.
Vineeth Chitteti

10

// thêm phiên bản java mà không cần đệ quy

public static <T> void find(TreeNode<T> node, int num){
    Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

    TreeNode<T> current = node;
    int tmp = num;

    while(stack.size() > 0 || current!=null){
        if(current!= null){
            stack.add(current);
            current = current.getLeft();
        }else{
            current = stack.pop();
            tmp--;

            if(tmp == 0){
                System.out.println(current.getValue());
                return;
            }

            current = current.getRight();
        }
    }
}

Tôi thích giải pháp này và giải pháp đệ quy tương ứng. Thành thật mà nói, hầu hết các câu trả lời cho câu hỏi này quá khó hiểu / phức tạp để đọc.
Henley Chiu

Tôi thích giải pháp này! Rõ ràng và tuyệt vời!
Rugal

Giải pháp này đang duyệt cây 'theo thứ tự' và giảm một bộ đếm sau khi truy cập vào nút, để sau đó dừng lại khi bộ đếm bằng không. Trường hợp xấu nhất là thứ tự O (n). Không phải là giải pháp tối ưu nhất so với các giải pháp đệ quy của @ IVlad có trường hợp xấu nhất lấy O (log n)
Jorge P.


4

Chỉ với một cây tìm kiếm nhị phân thuần túy, tất cả những gì bạn có thể làm là bắt đầu từ cái nhỏ nhất và đi ngược lên trên để tìm đúng nút.

Nếu bạn thường xuyên làm điều này, bạn có thể thêm một thuộc tính vào mỗi nút biểu thị có bao nhiêu nút trong cây con bên trái của nó. Sử dụng nó, bạn có thể hạ cây trực tiếp đến đúng nút.


4

Đi bộ theo thứ tự đệ quy với bộ đếm

Time Complexity: O( N ), N is the number of nodes
Space Complexity: O( 1 ), excluding the function call stack

Ý tưởng tương tự như giải pháp @prasadvk, nhưng nó có một số thiếu sót (xem ghi chú bên dưới), vì vậy tôi đăng bài này như một câu trả lời riêng biệt.

// Private Helper Macro
#define testAndReturn( k, counter, result )                         \
    do { if( (counter == k) && (result == -1) ) {                   \
        result = pn->key_;                                          \
        return;                                                     \
    } } while( 0 )

// Private Helper Function
static void findKthSmallest(
    BstNode const * pn, int const k, int & counter, int & result ) {

    if( ! pn ) return;

    findKthSmallest( pn->left_, k, counter, result );
    testAndReturn( k, counter, result );

    counter += 1;
    testAndReturn( k, counter, result );

    findKthSmallest( pn->right_, k, counter, result );
    testAndReturn( k, counter, result );
}

// Public API function
void findKthSmallest( Bst const * pt, int const k ) {
    int counter = 0;
    int result = -1;        // -1 := not found
    findKthSmallest( pt->root_, k, counter, result );
    printf("%d-th element: element = %d\n", k, result );
}

Lưu ý (và sự khác biệt so với giải pháp của @ prasadvk):

  1. if( counter == k )yêu cầu kiểm tra ở ba vị trí: (a) sau cây con bên trái, (b) sau gốc và (c) sau cây con bên phải. Điều này là để đảm bảo rằng phần tử thứ k được phát hiện cho tất cả các vị trí , tức là bất kể cây con mà nó nằm ở đâu.

  2. if( result == -1 )yêu cầu kiểm tra để đảm bảo chỉ in phần tử kết quả , nếu không tất cả các phần tử bắt đầu từ nhỏ nhất thứ k trở lên đều được in.


Thời gian phức tạp cho giải pháp này là O(k + d), nơi dlà max depth của cây. Do đó, nó sử dụng một biến toàn cục counternhưng nó là bất hợp pháp cho câu hỏi này.
Valentin Shergin

Xin chào Arun, bạn có thể vui lòng giải thích bằng một ví dụ. Tôi không hiểu điều này đặc biệt là điểm đầu tiên của bạn.
Andy897

3

Đối với cây tìm kiếm không cân bằng, phải lấy O (n) .

Đối với cân bằng cây tìm kiếm, phải mất O (k + n log) trong trường hợp xấu nhất, nhưng chỉ O (k) trong phân bổ dần ý nghĩa.

Có và quản lý số nguyên phụ cho mọi nút: kích thước của cây con cho độ phức tạp về thời gian là O (log n) . Cây tìm kiếm cân bằng như vậy thường được gọi là RankTree.

Nói chung, có các giải pháp (không dựa trên cây).

Trân trọng.


1

Điều này hoạt động tốt: status: là mảng chứa phần tử có được tìm thấy hay không. k: là phần tử thứ k cần tìm. count: theo dõi số lượng các nút được duyệt qua trong quá trình duyệt cây.

int kth(struct tree* node, int* status, int k, int count)
{
    if (!node) return count;
    count = kth(node->lft, status, k, count);  
    if( status[1] ) return status[0];
    if (count == k) { 
        status[0] = node->val;
        status[1] = 1;
        return status[0];
    }
    count = kth(node->rgt, status, k, count+1);
    if( status[1] ) return status[0];
    return count;
}

1

Mặc dù đây chắc chắn không phải là giải pháp tối ưu cho vấn đề, nhưng nó là một giải pháp tiềm năng khác mà tôi nghĩ một số người có thể thấy thú vị:

/**
 * Treat the bst as a sorted list in descending order and find the element 
 * in position k.
 *
 * Time complexity BigO ( n^2 )
 *
 * 2n + sum( 1 * n/2 + 2 * n/4 + ... ( 2^n-1) * n/n ) = 
 * 2n + sigma a=1 to n ( (2^(a-1)) * n / 2^a ) = 2n + n(n-1)/4
 *
 * @param t The root of the binary search tree.
 * @param k The position of the element to find.
 * @return The value of the element at position k.
 */
public static int kElement2( Node t, int k ) {
    int treeSize = sizeOfTree( t );

    return kElement2( t, k, treeSize, 0 ).intValue();
}

/**
 * Find the value at position k in the bst by doing an in-order traversal 
 * of the tree and mapping the ascending order index to the descending order 
 * index.
 *
 *
 * @param t Root of the bst to search in.
 * @param k Index of the element being searched for.
 * @param treeSize Size of the entire bst.
 * @param count The number of node already visited.
 * @return Either the value of the kth node, or Double.POSITIVE_INFINITY if 
 *         not found in this sub-tree.
 */
private static Double kElement2( Node t, int k, int treeSize, int count ) {
    // Double.POSITIVE_INFINITY is a marker value indicating that the kth 
    // element wasn't found in this sub-tree.
    if ( t == null )
        return Double.POSITIVE_INFINITY;

    Double kea = kElement2( t.getLeftSon(), k, treeSize, count );

    if ( kea != Double.POSITIVE_INFINITY )
        return kea;

    // The index of the current node.
    count += 1 + sizeOfTree( t.getLeftSon() );

    // Given any index from the ascending in order traversal of the bst, 
    // treeSize + 1 - index gives the
    // corresponding index in the descending order list.
    if ( ( treeSize + 1 - count ) == k )
        return (double)t.getNumber();

    return kElement2( t.getRightSon(), k, treeSize, count );
}

1

Chữ ký:

Node * find(Node* tree, int *n, int k);

gọi là:

*n = 0;
kthNode = find(root, n, k);

Định nghĩa:

Node * find ( Node * tree, int *n, int k)
{
   Node *temp = NULL;

   if (tree->left && *n<k)
      temp = find(tree->left, n, k);

   *n++;

   if(*n==k)
      temp = root;

   if (tree->right && *n<k)
      temp = find(tree->right, n, k);

   return temp;
}

1

Đây là 2 xu của tôi ...

int numBSTnodes(const Node* pNode){
     if(pNode == NULL) return 0;
     return (numBSTnodes(pNode->left)+numBSTnodes(pNode->right)+1);
}


//This function will find Kth smallest element
Node* findKthSmallestBSTelement(Node* root, int k){
     Node* pTrav = root;
     while(k > 0){
         int numNodes = numBSTnodes(pTrav->left);
         if(numNodes >= k){
              pTrav = pTrav->left;
         }
         else{
              //subtract left tree nodes and root count from 'k'
              k -= (numBSTnodes(pTrav->left) + 1);
              if(k == 0) return pTrav;
              pTrav = pTrav->right;
        }

        return NULL;
 }

0

Đây là những gì tôi mặc dù và nó hoạt động. Nó sẽ chạy trong o (log n)

public static int FindkThSmallestElemet(Node root, int k)
    {
        int count = 0;
        Node current = root;

        while (current != null)
        {
            count++;
            current = current.left;
        }
        current = root;

        while (current != null)
        {
            if (count == k)
                return current.data;
            else
            {
                current = current.left;
                count--;
            }
        }

        return -1;


    } // end of function FindkThSmallestElemet

3
tôi không nghĩ rằng giải pháp này sẽ hoạt động. Điều gì xảy ra nếu K nhỏ nhất nằm trong cây con bên phải của nút cây?
Anil Vishnoi

0

Chúng ta có thể chỉ cần sử dụng trình duyệt theo thứ tự và đẩy phần tử đã thăm vào một ngăn xếp. bật k số lần, để có câu trả lời.

chúng ta cũng có thể dừng lại sau k phần tử


1
đây không phải là một giải pháp tối ưu
bragboy

0

Giải pháp cho trường hợp BST hoàn chỉnh: -

Node kSmallest(Node root, int k) {
  int i = root.size(); // 2^height - 1, single node is height = 1;
  Node result = root;
  while (i - 1 > k) {
    i = (i-1)/2;  // size of left subtree
    if (k < i) {
      result = result.left;
    } else {
      result = result.right;
      k -= i;
    }  
  }
  return i-1==k ? result: null;
}

0

Nhân Linux có cấu trúc dữ liệu cây đỏ-đen tăng cường tuyệt vời hỗ trợ các hoạt động dựa trên thứ hạng trong O (log n) trong linux / lib / rbtree.c.

Bạn cũng có thể tìm thấy một cổng Java rất thô tại http://code.google.com/p/refolding/source/browse/trunk/core/src/main/java/it/unibo/refolding/alg/RbTree.java , cùng với RbRoot.java và RbNode.java. Phần tử thứ n có thể được lấy bằng cách gọi RbNode.nth (nút RbNode, int n), truyền vào gốc của cây.


0

Dưới đây là một phiên bản ngắn gọn trong C # rằng lợi nhuận là thứ k phần tử nhỏ nhất, nhưng đòi hỏi phải đi qua k trong như một đối số ref (đó là cách tiếp cận tương tự như @prasadvk):

Node FindSmall(Node root, ref int k)
{
    if (root == null || k < 1)
        return null;

    Node node = FindSmall(root.LeftChild, ref k);
    if (node != null)
        return node;

    if (--k == 0)
        return node ?? root;
    return FindSmall(root.RightChild, ref k);
}

Đó là O (log n) để tìm các nút nhỏ nhất, và sau đó O (k) đi qua để k-th nút, vì vậy nó O (k + log n).


làm thế nào về phiên bản java?
Henley Chiu


0

Tôi không thể tìm thấy một thuật toán tốt hơn..vì vậy tôi quyết định viết một thuật toán :) Hãy sửa cho tôi nếu điều này sai.

class KthLargestBST{
protected static int findKthSmallest(BSTNode root,int k){//user calls this function
    int [] result=findKthSmallest(root,k,0);//I call another function inside
    return result[1];
}
private static int[] findKthSmallest(BSTNode root,int k,int count){//returns result[]2 array containing count in rval[0] and desired element in rval[1] position.
    if(root==null){
        int[]  i=new int[2];
        i[0]=-1;
        i[1]=-1;
        return i;
    }else{
        int rval[]=new int[2];
        int temp[]=new int[2];
        rval=findKthSmallest(root.leftChild,k,count);
        if(rval[0]!=-1){
            count=rval[0];
        }
        count++;
        if(count==k){
            rval[1]=root.data;
        }
        temp=findKthSmallest(root.rightChild,k,(count));
        if(temp[0]!=-1){
            count=temp[0];
        }
        if(temp[1]!=-1){
            rval[1]=temp[1];
        }
        rval[0]=count;
        return rval;
    }
}
public static void main(String args[]){
    BinarySearchTree bst=new BinarySearchTree();
    bst.insert(6);
    bst.insert(8);
    bst.insert(7);
    bst.insert(4);
    bst.insert(3);
    bst.insert(4);
    bst.insert(1);
    bst.insert(12);
    bst.insert(18);
    bst.insert(15);
    bst.insert(16);
    bst.inOrderTraversal();
    System.out.println();
    System.out.println(findKthSmallest(bst.root,11));
}

}


0

Đây là mã java,

max (Node root, int k) - để tìm lớn thứ k

min (Node root, int k) - để tìm thứ k Nhỏ nhất

static int count(Node root){
    if(root == null)
        return 0;
    else
        return count(root.left) + count(root.right) +1;
}
static int max(Node root, int k) {
    if(root == null)
        return -1;
    int right= count(root.right);

    if(k == right+1)
        return root.data;
    else if(right < k)
        return max(root.left, k-right-1);
    else return max(root.right, k);
}

static int min(Node root, int k) {
    if (root==null)
        return -1;

    int left= count(root.left);
    if(k == left+1)
        return root.data;
    else if (left < k)
        return min(root.right, k-left-1);
    else
        return min(root.left, k);
}

0

điều này cũng sẽ hoạt động. chỉ cần gọi hàm với maxNode trong cây

def k_largest (self, node, k): if k <0: return None
if k == 0: return node else: k - = 1 return self.k_largest (self.pred Cần thiết (node), k)


0

Tôi nghĩ điều này tốt hơn câu trả lời được chấp nhận vì nó không cần phải sửa đổi nút cây ban đầu để lưu trữ số lượng nút con của nó.

Chúng ta chỉ cần sử dụng phép duyệt theo thứ tự để đếm nút nhỏ nhất từ ​​trái sang phải, ngừng tìm kiếm khi số đếm bằng K.

private static int count = 0;
public static void printKthSmallestNode(Node node, int k){
    if(node == null){
        return;
    }

    if( node.getLeftNode() != null ){
        printKthSmallestNode(node.getLeftNode(), k);
    }

    count ++ ;
    if(count <= k )
        System.out.println(node.getValue() + ", count=" + count + ", k=" + k);

    if(count < k  && node.getRightNode() != null)
        printKthSmallestNode(node.getRightNode(), k);
}

0

Phương pháp tốt nhất đã có. Nhưng tôi muốn thêm một Mã đơn giản cho điều đó

int kthsmallest(treenode *q,int k){
int n = size(q->left) + 1;
if(n==k){
    return q->val;
}
if(n > k){
    return kthsmallest(q->left,k);
}
if(n < k){
    return kthsmallest(q->right,k - n);
}

}

int size(treenode *q){
if(q==NULL){
    return 0;
}
else{
    return ( size(q->left) + size(q->right) + 1 );
}}

0

Sử dụng lớp Kết quả phụ trợ để theo dõi xem có tìm thấy nút hay không và hiện tại k.

public class KthSmallestElementWithAux {

public int kthsmallest(TreeNode a, int k) {
    TreeNode ans = kthsmallestRec(a, k).node;
    if (ans != null) {
        return ans.val;
    } else {
        return -1;
    }
}

private Result kthsmallestRec(TreeNode a, int k) {
    //Leaf node, do nothing and return
    if (a == null) {
        return new Result(k, null);
    }

    //Search left first
    Result leftSearch = kthsmallestRec(a.left, k);

    //We are done, no need to check right.
    if (leftSearch.node != null) {
        return leftSearch;
    }

    //Consider number of nodes found to the left
    k = leftSearch.k;

    //Check if current root is the solution before going right
    k--;
    if (k == 0) {
        return new Result(k - 1, a);
    }

    //Check right
    Result rightBalanced = kthsmallestRec(a.right, k);

    //Consider all nodes found to the right
    k = rightBalanced.k;

    if (rightBalanced.node != null) {
        return rightBalanced;
    }

    //No node found, recursion will continue at the higher level
    return new Result(k, null);

}

private class Result {
    private final int k;
    private final TreeNode node;

    Result(int max, TreeNode node) {
        this.k = max;
        this.node = node;
    }
}
}

0

Giải pháp Python Độ phức tạp về thời gian: O (n) Độ phức tạp về không gian: O (1)

Ý tưởng là sử dụng Morris Inorder Traversal

class Solution(object):
def inorderTraversal(self, current , k ):
    while(current is not None):    #This Means we have reached Right Most Node i.e end of LDR traversal

        if(current.left is not None):  #If Left Exists traverse Left First
            pre = current.left   #Goal is to find the node which will be just before the current node i.e predecessor of current node, let's say current is D in LDR goal is to find L here
            while(pre.right is not None and pre.right != current ): #Find predecesor here
                pre = pre.right
            if(pre.right is None):  #In this case predecessor is found , now link this predecessor to current so that there is a path and current is not lost
                pre.right = current
                current = current.left
            else:                   #This means we have traverse all nodes left to current so in LDR traversal of L is done
                k -= 1
                if(k == 0):
                    return current.val
                pre.right = None       #Remove the link tree restored to original here 
                current = current.right
        else:               #In LDR  LD traversal is done move to R 
            k -= 1
            if(k == 0):
                return current.val
            current = current.right

    return 0

def kthSmallest(self, root, k):
    return self.inorderTraversal( root , k  )

-1

tôi đã viết một hàm gọn gàng để tính phần tử nhỏ nhất thứ k. Tôi sử dụng truyền theo thứ tự và dừng lại khi nó đạt đến phần tử nhỏ nhất thứ k.

void btree::kthSmallest(node* temp, int& k){
if( temp!= NULL)   {
 kthSmallest(temp->left,k);       
 if(k >0)
 {
     if(k==1)
    {
      cout<<temp->value<<endl;
      return;
    }

    k--;
 }

 kthSmallest(temp->right,k);  }}

Không có số liệu nào được cung cấp về lý do tại sao điều này là tối ưu. Trong cả hai trường hợp lớn và nhỏ
Woot4Moo

-1
int RecPrintKSmallest(Node_ptr head,int k){
  if(head!=NULL){
    k=RecPrintKSmallest(head->left,k);
    if(k>0){
      printf("%c ",head->Node_key.key);
      k--;
    }
    k=RecPrintKSmallest(head->right,k);
  }
  return k;
}

2
Vui lòng luôn kèm theo mã với một số cấp độ mô tả về chức năng của nó và cách nó giúp giải quyết vấn đề.
Ren

-1
public TreeNode findKthElement(TreeNode root, int k){
    if((k==numberElement(root.left)+1)){
        return root;
    }
    else if(k>numberElement(root.left)+1){
        findKthElement(root.right,k-numberElement(root.left)-1);
    }
    else{
        findKthElement(root.left, k);
    }
}

public int numberElement(TreeNode node){
    if(node==null){
        return 0;
    }
    else{
        return numberElement(node.left) + numberElement(node.right) + 1;
    }
}

-1
public static Node kth(Node n, int k){
    Stack<Node> s=new Stack<Node>();
    int countPopped=0;
    while(!s.isEmpty()||n!=null){
      if(n!=null){
        s.push(n);
        n=n.left;
      }else{
        node=s.pop();
        countPopped++;
        if(countPopped==k){
            return node;
        }
        node=node.right;

      }
  }

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.