给定具有子节点的二叉树,返回一个随机节点,其选择树中任何节点的可能性相同。
考虑根为1的给定树。
10
/ \
20 30
/ \ / \
40 50 60 70
例子:
Input : getRandom(root);
Output : A Random Node From Tree : 3
Input : getRandom(root);
Output : A Random Node From Tree : 2
一个简单的解决方案是将树的有序遍历存储在数组中。设节点数为n。为了获得一个随机节点,我们生成一个从0到n-1的随机数,将该数字用作数组中的索引,然后返回index处的值。
另一种解决方案是修改树结构。我们在每个节点中存储孩子数。考虑上面的树。我们在这里也使用有序遍历。我们生成一个小于或等于节点数的数字。我们遍历树并转到该索引处的节点。我们使用计数来快速到达所需的节点。通过计数,我们到达O(h)时间,其中h是树的高度。
10,6
/ \
20,2 30,2
/ \ / \
40,0 50,0 60,0 70,0
The first value is node and second
value is count of children.
我们开始遍历这棵树,在每个节点上,我们都转到左子树或右子树,考虑子代数是否小于随机数。
如果随机数小于孩子数,则我们向左走,否则我们向右走。
下面是上述算法的实现。 getElements将返回root的子代计数,InsertChildrenCount将子代数据插入每个节点,RandomNode在实用程序函数RandomNodeUtil的帮助下返回随机节点。
C++
// CPP program to Select a Random Node from a tree
#include
using namespace std;
struct Node {
int data;
int children;
Node *left, *right;
};
Node* newNode(int data)
{
Node *temp = new Node;
temp->data = data;
temp->left = temp->right = NULL;
temp->children = 0;
return temp;
}
// This is used to fill children counts.
int getElements(Node* root)
{
if (!root)
return 0;
return getElements(root->left) +
getElements(root->right) + 1;
}
// Inserts Children count for each node
void insertChildrenCount(Node*& root)
{
if (!root)
return;
root->children = getElements(root) - 1;
insertChildrenCount(root->left);
insertChildrenCount(root->right);
}
// returns number of children for root
int children(Node* root)
{
if (!root)
return 0;
return root->children + 1;
}
// Helper Function to return a random node
int randomNodeUtil(Node* root, int count)
{
if (!root)
return 0;
if (count == children(root->left))
return root->data;
if (count < children(root->left))
return randomNodeUtil(root->left, count);
return randomNodeUtil(root->right,
count - children(root->left) - 1);
}
// Returns Random node
int randomNode(Node* root)
{
srand(time(0));
int count = rand() % (root->children + 1);
return randomNodeUtil(root, count);
}
int main()
{
// Creating Above Tree
Node* root = newNode(10);
root->left = newNode(20);
root->right = newNode(30);
root->left->right = newNode(40);
root->left->right = newNode(50);
root->right->left = newNode(60);
root->right->right = newNode(70);
insertChildrenCount(root);
cout << "A Random Node From Tree : "
<< randomNode(root) << endl;
return 0;
}
Java
// Java program to Select a Random Node from a tree
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG
{
static class Node
{
int data;
int children;
Node left, right;
}
static Node newNode(int data)
{
Node temp = new Node();
temp.data = data;
temp.left = temp.right = null;
temp.children = 0;
return temp;
}
// This is used to fill children counts.
static int getElements(Node root)
{
if (root == null)
return 0;
return getElements(root.left) +
getElements(root.right) + 1;
}
// Inserts Children count for each node
static Node insertChildrenCount(Node root)
{
if (root == null)
return null;
root.children = getElements(root) - 1;
root.left = insertChildrenCount(root.left);
root.right = insertChildrenCount(root.right);
return root;
}
// returns number of children for root
static int children(Node root)
{
if (root == null)
return 0;
return root.children + 1;
}
// Helper Function to return a random node
static int randomNodeUtil(Node root, int count)
{
if (root == null)
return 0;
if (count == children(root.left))
return root.data;
if (count < children(root.left))
return randomNodeUtil(root.left, count);
return randomNodeUtil(root.right,
count - children(root.left) - 1);
}
// Returns Random node
static int randomNode(Node root)
{
int count = (int) Math.random() *
(root.children + 1);
return randomNodeUtil(root, count);
}
// Driver Code
public static void main(String args[])
{
// Creating Above Tree
Node root = newNode(10);
root.left = newNode(20);
root.right = newNode(30);
root.left.right = newNode(40);
root.left.right = newNode(50);
root.right.left = newNode(60);
root.right.right = newNode(70);
insertChildrenCount(root);
System.out.println( "A Random Node From Tree : " +
randomNode(root));
}
}
// This code is contributed by Arnab Kundu
Python3
# Python3 program to Select a
# Random Node from a tree
from random import randint
class Node:
def __init__(self, data):
self.data = data
self.children = 0
self.left = None
self.right = None
# This is used to fill children counts.
def getElements(root):
if root == None:
return 0
return (getElements(root.left) +
getElements(root.right) + 1)
# Inserts Children count for each node
def insertChildrenCount(root):
if root == None:
return
root.children = getElements(root) - 1
insertChildrenCount(root.left)
insertChildrenCount(root.right)
# Returns number of children for root
def children(root):
if root == None:
return 0
return root.children + 1
# Helper Function to return a random node
def randomNodeUtil(root, count):
if root == None:
return 0
if count == children(root.left):
return root.data
if count < children(root.left):
return randomNodeUtil(root.left, count)
return randomNodeUtil(root.right,
count - children(root.left) - 1)
# Returns Random node
def randomNode(root):
count = randint(0, root.children)
return randomNodeUtil(root, count)
# Driver Code
if __name__ == "__main__":
# Creating Above Tree
root = Node(10)
root.left = Node(20)
root.right = Node(30)
root.left.right = Node(40)
root.left.right = Node(50)
root.right.left = Node(60)
root.right.right = Node(70)
insertChildrenCount(root)
print("A Random Node From Tree :",
randomNode(root))
# This code is contributed by Rituraj Jain
C#
// C# program to Select a Random Node from a tree
using System;
class GFG
{
class Node
{
public int data;
public int children;
public Node left, right;
}
static Node newNode(int data)
{
Node temp = new Node();
temp.data = data;
temp.left = temp.right = null;
temp.children = 0;
return temp;
}
// This is used to fill children counts.
static int getElements(Node root)
{
if (root == null)
return 0;
return getElements(root.left) +
getElements(root.right) + 1;
}
// Inserts Children count for each node
static Node insertChildrenCount(Node root)
{
if (root == null)
return null;
root.children = getElements(root) - 1;
root.left = insertChildrenCount(root.left);
root.right = insertChildrenCount(root.right);
return root;
}
// returns number of children for root
static int children(Node root)
{
if (root == null)
return 0;
return root.children + 1;
}
// Helper Function to return a random node
static int randomNodeUtil(Node root, int count)
{
if (root == null)
return 0;
if (count == children(root.left))
return root.data;
if (count < children(root.left))
return randomNodeUtil(root.left, count);
return randomNodeUtil(root.right,
count - children(root.left) - 1);
}
// Returns Random node
static int randomNode(Node root)
{
int count = (int) new Random().Next(0, root.children + 1);
return randomNodeUtil(root, count);
}
// Driver Code
public static void Main(String []args)
{
// Creating Above Tree
Node root = newNode(10);
root.left = newNode(20);
root.right = newNode(30);
root.left.right = newNode(40);
root.left.right = newNode(50);
root.right.left = newNode(60);
root.right.right = newNode(70);
insertChildrenCount(root);
Console.Write( "A Random Node From Tree : " +
randomNode(root));
}
}
// This code is contributed by Arnab Kundu
randomNode的时间复杂度为O(h),其中h是树的高度。请注意,我们一次或向右移动或向左移动。