Comment trouver le Nème plus grand noeud d'un BST?
Est-ce que je garde une variable de comptage lors de la traversée dans l'ordre d'une BST? Renvoie l'élément lorsque le compte = N ???
Voir ma réponse ici . Vous pouvez le faire dans O(log n)
en moyenne où n = nombre de nœuds. Le cas le plus défavorable reste toujours O(n)
SI l'arbre n'est pas équilibré (toujours O(log n)
s'il est équilibré). Dans l'ordre, la traversée est toujours O(n)
cependant.
L'idée est très simple: parcourez l'arbre dans l'ordre décroissant des valeurs de chaque nœud. Lorsque vous atteignez le nœud Nth, imprimez cette valeur de nœud. Voici le code récursif.
void printNthNode(Node* root, int N)
{
if(root == NULL)
return;
static int index = 0; //These will initialize to zero only once as its static
//For every Node go to the right of that node first.
printNthNode(root->right, N);
//Right has returned and now current node will be greatest
if(++index == N)
{
printf("%d\n", root->data);
return;
}
//And at last go to the left
printNthNode(root->left, N);
}
Modifier - Selon les commentaires ci-dessous, il semblerait que ce soit une fonction d'appel unique due à la variable locale statique. Ceci peut être résolu en passant l'objet wrapper pour index
comme suit:
class WrapIndex {
public: int index;
};
et la signature de la méthode changerait à
void printNthNode(Node* root, int N, WrapIndex wrapInd)
Maintenant, nous n’avons pas besoin d’une variable statique locale; utilisez plutôt index
de l'objet wrapper. L'appel ressemblerait à
WrapIndex wrapInd = new WrapIndex();
wrapInd.index=0;
printNthNode(root,7,wrapInd);
wrapInd.index=0;
printNthNode(root,2,wrapInd);
Astuce: utilisez inorder traversal de l’arbre. Il peut imprimer les éléments dans un ordre trié afin que vous puissiez trouver le Nème élément le plus volumineux. Gardez un compteur pendant que vous "marchez", en augmentant chaque fois que vous "visitez" un nœud.
Éditer : Bien que la réponse d'IVlad soit effectivement plus rapide, elle nécessite de conserver des informations supplémentaires dans les nœuds. Cette réponse ne fonctionne pas mais c'est O(n)
. En soulignant que c'est un compromis dont vous devez être conscient.
Conservez la taille du sous-arbre à chaque noeud (root.size quelque chose comme ça). Par exemple, {2,3,1} est un arbre binaire avec la racine 2, la taille du noeud (2) est égale à 3, la taille du noeud (1) est égale à 1 et la taille du noeud (2) est égale à 1.
si vous voulez trouver le 4 ème élément larget dans l’arbre avec une taille de nœud racine 23, pensez à son rang
le rang maximum d'éléments est 23, car la taille du nœud racine est 23. Le rang rang 4 des éléments les plus importants est 23-4 + 1 = 20
nous devons donc trouver le 20ème élément de rang dans l'arbre donné
déclarer initialement un rang = 0 drapeau à zéro
en partant du noeud racine, trouvez son rang (rang + taille de l'enfant gauche + 1), par exemple, sa taille est de 16 puis le rang de l'élément racine est de 17 (rang + taille de son enfant +1)
donc nous devons rechercher l'élément avec le rang 20 alors évidemment nous devons traverser jusqu'à son enfant droit
traversez vers le bon enfant et sur la base de la formule ci-dessus, trouvez le bon rang pour l'enfant (sur la base de la formule ci-dessus, remarque: la valeur du drapeau de rang est maintenant égale à 17), indiquez si vous souhaitez aller à droite ou à gauche selon le rang
Ce morceau de code provient de mon affectation et l'une des conditions était de ne pas utiliser les tableaux Afin de rendre le code plus compact et lisible, vous pouvez utiliser StringName.split ("|"). Comme la méthode est récursive, j'utilise le stringBuilder Qui a la structure suivante: "counter | orderOfElementToFind | dataInrequiredNode"
protected StringBuilder t(StringBuilder s)
{
if (lc != null)
{
lc.t(s);
}
if((s.toString().charAt(s.toString().length() - 1)) == '|')
{
String str = s.toString();
s.delete(0, s.length());
int counter = 0, k = 0;
String strTemp = "", newStrBuilContent = "";
for (int i = 0, c = 0 ; i < str.length(); ++i)
{
if (c == 0)
{
if (str.charAt(i) != '|')
{
strTemp += str.charAt(i);
}
else
{
counter = Integer.parseInt(strTemp);
++c;
strTemp = "";
}
}
else
{
if (str.charAt(i) != '|')
{
strTemp += str.charAt(i);
}
else
{
k = Integer.parseInt(strTemp);
}
}
counter ++;
newStrBuilContent = (counter + "|" + k + "|");
s.append(newStrBuilContent);
if (counter == k)
{
double ldata = this.getData();
s.append(ldata);
}
}
if (rc != null)
{
rc.t(s);
}
return s;
}
et l'appel de méthode:
// the value of counter ad the beginning is 0 and data
// segment is missing
String s = ("0|" + order +"|");
StringBuilder strBldr = new StringBuilder(s);
String content = sTree.t(strBldr).toString();
s = "";
for (int i = 0, c = 0; i < content.length(); ++i)
{
if (c < 2)
{
if (content.charAt(i) == '|')
{
++c;
}
}
else
{
s += content.charAt(i);
}
}
`
Utilisez un ordre inverse inversé. C’est-à-dire aller à l’enfant droit en premier au lieu de l’enfant gauche . De manière récursive, on peut l’obtenir de la manière suivante:.
reverseInorder(root){
if(root!=null){
reverseInorder(root->rightChild);
self
reverseInorder(root->leftChild);
}
}
Solution en Java
package datastructure.binaryTree;
import datastructure.nodes.BinaryTreeNode;
public class NthElementFromEnd {
private BinaryTree tree=null;
int currCount=0;
public NthElementFromEnd(int[] dataArray) {
this.tree=new BinaryTree(dataArray);
}
private void getElementFromEnd(int n){
getElementFromEnd(this.tree.getRoot(),n);
}
private void getElementFromEnd(BinaryTreeNode node,int n){
if(node!=null){
if(currCount<n)
getElementFromEnd(node.getRightChild(),n);
currCount++;
if(currCount==n)
{
System.out.print(" "+node.getData());
return;
}
if(currCount<n)
getElementFromEnd(node.getLeftChild(),n);
}
}
public static void main(String args[]){
int data[]={1,2,3,4,5,6,7,8,9};
int n=2;
new NthElementFromEnd(data).getElementFromEnd(n);
}
}
// C++ program to find k'th largest element in BST
#include<iostream>
using namespace std;
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 function to find k'th largest element in a given tree.
void kthLargestUtil(Node *root, int k, int &c)
{
// Base cases, the second condition is important to
// avoid unnecessary recursive calls
if (root == NULL || c >= k)
return;
// Follow reverse inorder traversal so that the
// largest element is visited first
kthLargestUtil(root->right, k, c);
// Increment count of visited nodes
c++;
// If c becomes k now, then this is the k'th largest
if (c == k)
{
cout << "K'th largest element is "
<< root->key << endl;
return;
}
// Recur for left subtree
kthLargestUtil(root->left, k, c);
}
// Function to find k'th largest element
void kthLargest(Node *root, int k)
{
// Initialize count of nodes visited as 0
int c = 0;
// Note that c is passed by reference
kthLargestUtil(root, k, c);
}
/* A utility function to insert a new node with given key in BST */
Node* insert(Node* node, int key)
{
/* If the tree is empty, return a new node */
if (node == NULL) return newNode(key);
/* Otherwise, recur down the tree */
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
/* return the (unchanged) node pointer */
return node;
}
// Driver Program to test above functions
int main()
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
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);
int c = 0;
for (int k=1; k<=7; k++)
kthLargest(root, k);
return 0;
}
Je le ferais en allant de l'arbre du plus grand au plus petit élément et en retournant une valeur lorsque la position demandée est atteinte J'ai mis en œuvre une tâche similaire pour la deuxième plus grande valeur. La valeur 2 est codée en dur, mais est-il facile de changer avec un paramètre supplémentaire :)
void BTree::findSecondLargestValueUtil(Node* r, int &c, int &v)
{
if(r->right) {
this->findSecondLargestValueUtil(r->right, c, v);
}
c++;
if(c==2) {
v = r->value;
return;
}
if(r->left) {
this->findSecondLargestValueUtil(r->left, c, v);
}
}
int BTree::findSecondLargestValue()
{
int c = 0;
int v = -1;
this->findSecondLargestValueUtil(this->root, c, v);
return v;
}
int nLargeBST(node *root, int N) {
if (!root || N < 0) {
return -1;
}
nLargeBST(root->left, N);
--N;
if(N == 0) {
return root->val;
}
nLargeBST(root->right, N);
}