Given a singly linked list, select a random node from the linked list (the probability of picking a node should be 1/N if there are N nodes in the list). You are given a random number generator.
Below is a Simple Solution
- Count the number of nodes by traversing the list.
- Traverse the list again and select every node with a probability of 1/N. The selection can be done by generating a random number from 0 to N-i for the node, and selecting the i’th node only if the generated number is equal to 0 (or any other fixed number from 0 to N-i).
We get uniform probabilities with the above schemes.
i = 1, probability of selecting first node = 1/N
i = 2, probability of selecting second node =
[probability that first node is not selected] *
[probability that second node is selected]
= ((N-1)/N)* 1/(N-1)
= 1/N
Similarly, the probability of other selecting other nodes is 1/N
The above solution requires two traversals of the linked list.
How to select a random node with only one traversal allowed?
The idea is to use Reservoir Sampling. Following are the steps. This is a simpler version of Reservoir Sampling as we need to select only one key instead of the k keys.
(1) Initialize result as first node
result = head->key
(2) Initialize n = 2
(3) Now one by one consider all nodes from 2nd node onward.
(3.a) Generate a random number from 0 to n-1.
Let the generated random number is j.
(3.b) If j is equal to 0 (we could choose other fixed number
between 0 to n-1), then replace result with current node.
(3.c) n = n+1
(3.d) current = current->next
Below is the implementation of the above algorithm.
C++
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
#include<iostream>
using namespace std;
class Node
{
public :
int key;
Node* next;
void printRandom(Node*);
void push(Node**, int );
};
void Node::printRandom(Node *head)
{
if (head == NULL)
return ;
srand ( time (NULL));
int result = head->key;
Node *current = head;
int n;
for (n = 2; current != NULL; n++)
{
if ( rand () % n == 0)
result = current->key;
current = current->next;
}
cout<< "Randomly selected key is \n" << result;
}
Node* newNode( int new_key)
{
Node* new_node = (Node*) malloc ( sizeof ( Node));
new_node->key = new_key;
new_node->next = NULL;
return new_node;
}
void Node:: push(Node** head_ref, int new_key)
{
Node* new_node = new Node;
new_node->key = new_key;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
int main()
{
Node n1;
Node *head = NULL;
n1.push(&head, 5);
n1.push(&head, 20);
n1.push(&head, 4);
n1.push(&head, 3);
n1.push(&head, 30);
n1.printRandom(head);
return 0;
}
|
C
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
struct Node
{
int key;
struct Node* next;
};
void printRandom( struct Node *head)
{
if (head == NULL)
return ;
srand ( time (NULL));
int result = head->key;
struct Node *current = head;
int n;
for (n=2; current!=NULL; n++)
{
if ( rand () % n == 0)
result = current->key;
current = current->next;
}
printf ( "Randomly selected key is %d\n" , result);
}
struct Node *newNode( int new_key)
{
struct Node* new_node =
( struct Node*) malloc ( sizeof ( struct Node));
new_node->key = new_key;
new_node->next = NULL;
return new_node;
}
void push( struct Node** head_ref, int new_key)
{
struct Node* new_node = new Node;
new_node->key = new_key;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
int main()
{
struct Node *head = NULL;
push(&head, 5);
push(&head, 20);
push(&head, 4);
push(&head, 3);
push(&head, 30);
printRandom(head);
return 0;
}
|
Java
import java.util.*;
class LinkedList {
static Node head;
static class Node {
int data;
Node next;
Node( int d) {
data = d;
next = null ;
}
}
void printrandom(Node node) {
if (node == null ) {
return ;
}
Math.abs(UUID.randomUUID().getMostSignificantBits());
int result = node.data;
Node current = node;
int n;
for (n = 2 ; current != null ; n++) {
if (Math.random() % n == 0 ) {
result = current.data;
}
current = current.next;
}
System.out.println( "Randomly selected key is " + result);
}
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.head = new Node( 5 );
list.head.next = new Node( 20 );
list.head.next.next = new Node( 4 );
list.head.next.next.next = new Node( 3 );
list.head.next.next.next.next = new Node( 30 );
list.printrandom(head);
}
}
|
Python3
import random
class Node:
def __init__( self , data):
self .data = data
self . next = None
class LinkedList:
def __init__( self ):
self .head = None
def printRandom( self ):
if self .head is None :
return
if self .head and not self .head. next :
print ( "Randomly selected key is %d" % ( self .head.data))
random.seed()
result = self .head.data
current = self .head. next
n = 2
while (current is not None ):
if (random.randrange(n) = = 0 ):
result = current.data
current = current. next
n + = 1
print ( "Randomly selected key is %d" % (result))
def push( self , new_data):
new_node = Node(new_data)
new_node. next = self .head
self .head = new_node
def printList( self ):
temp = self .head
while (temp):
print (temp.data,end = " " )
temp = temp. next
llist = LinkedList()
llist.push( 5 )
llist.push( 20 )
llist.push( 4 )
llist.push( 3 )
llist.push( 30 )
llist.printRandom()
|
C#
using System;
public class LinkedList
{
Node head;
public class Node
{
public int data;
public Node next;
public Node( int d)
{
data = d;
next = null ;
}
}
void printrandom(Node node)
{
if (node == null )
{
return ;
}
int result = node.data;
Node current = node;
int n;
for (n = 2; current != null ; n++)
{
if ( new Random().Next() % n == 0)
{
result = current.data;
}
current = current.next;
}
Console.WriteLine( "Randomly selected key is " +
result);
}
public static void Main(String[] args)
{
LinkedList list = new LinkedList();
list.head = new Node(5);
list.head.next = new Node(20);
list.head.next.next = new Node(4);
list.head.next.next.next = new Node(3);
list.head.next.next.next.next = new Node(30);
list.printrandom(list.head);
}
}
|
Javascript
<script>
class Node
{
constructor(d)
{
this .data=d;
this .next = null ;
}
}
function printrandom(node)
{
if (node == null ) {
return ;
}
let result = node.data;
let current = node;
let n;
for (n = 2; current != null ; n++) {
if (Math.floor(Math.random()*n) == 0) {
result = current.data;
}
current = current.next;
}
document.write( "Randomly selected key is <br>" +
result+ "<br>" );
}
head = new Node(5);
head.next = new Node(20);
head.next.next = new Node(4);
head.next.next.next = new Node(3);
head.next.next.next.next = new Node(30);
printrandom(head);
</script>
|
Output
Randomly selected key is
4
Time Complexity: O(n), as we are using a loop to traverse n times. Where n is the number of nodes in the linked list.
Auxiliary Space: O(1), as we are not using any extra space.
Note that the above program is based on the outcome of a random function and may produce different outputs.
How does this work?
Let there be total N nodes in the list. It is easier to understand from the last node.
The probability that the last node is result simply 1/N [For the last or N’th node, we generate a random number between 0 to N-1 and make the last node as the result if the generated number is 0 (or any other fixed number]
The probability that the second last node is the result should also be 1/N.
The probability that the second last node is result
= [Probability that the second last node replaces result] X
[Probability that the last node doesn't replace the result]
= [1 / (N-1)] * [(N-1)/N]
= 1/N
Similarly, we can show the probability for 3rd last node and other nodes.
Another approach Using rand() Function:
Here in this Approach, we convert linked list to vector by storing every node value and than we apply rand() function on them and return the random node value.
Approach/Intuition:
here given linked list :
- 5 -> 20 -> 4 -> 3 -> 30.
- we traverse over linked list and convert it into vector.
- vector<int>v{5,20,4,3,30};
- than we use rand() function.
- int n=v.size() //size of the vector.
- int RandomIndex=rand() % n;
- and at the end we will return random node value from singly linked list.
Below is the code to implement the above approach:
C++
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
class Node {
public :
int key;
Node* next;
void printRandom(Node*);
void push(Node**, int );
};
Node* newNode( int new_key)
{
Node* new_node = (Node*) malloc ( sizeof (Node));
new_node->key = new_key;
new_node->next = NULL;
return new_node;
}
void Node::push(Node** head_ref, int new_key)
{
Node* new_node = new Node;
new_node->key = new_key;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printRandom(Node* head)
{
Node* temp = head;
vector< int > v;
while (temp != NULL) {
v.push_back(temp->key);
temp = temp->next;
}
int n = v.size();
int randIndex = rand () % n;
cout << v[randIndex] << endl;
}
int main()
{
Node n1;
Node* head = NULL;
n1.push(&head, 5);
n1.push(&head, 20);
n1.push(&head, 4);
n1.push(&head, 3);
n1.push(&head, 30);
printRandom(head);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class Node {
int key;
Node next;
Node( int key)
{
this .key = key;
this .next = null ;
}
}
class GFG {
public static void printRandom(Node head)
{
Node temp = head;
ArrayList<Integer> list = new ArrayList<Integer>();
while (temp != null ) {
list.add(temp.key);
temp = temp.next;
}
int n = list.size();
Random rand = new Random();
int randIndex = rand.nextInt(n);
System.out.println(list.get(randIndex));
}
public static void main(String[] args)
{
Node head = new Node( 30 );
head.next = new Node( 3 );
head.next.next = new Node( 4 );
head.next.next.next = new Node( 20 );
head.next.next.next.next = new Node( 5 );
printRandom(head);
}
}
|
Python3
import random
class Node:
def __init__( self ):
self .key = 0
self . next = None
def push( self , head_ref, new_key):
new_node = Node()
new_node.key = new_key
new_node. next = head_ref
head_ref = new_node
return head_ref
@staticmethod
def printRandom(head):
temp = head
v = []
while temp ! = None :
v.append(temp.key)
temp = temp. next
n = len (v)
randIndex = random.randint( 0 , n - 1 )
print (v[randIndex])
if __name__ = = '__main__' :
n1 = Node()
head = None
head = n1.push(head, 5 )
head = n1.push(head, 20 )
head = n1.push(head, 4 )
head = n1.push(head, 3 )
head = n1.push(head, 30 )
Node.printRandom(head)
|
C#
using System;
using System.Collections.Generic;
public class Node {
public int key;
public Node next;
public Node( int key)
{
this .key = key;
this .next = null ;
}
}
public class GFG {
public static void printRandom(Node head)
{
Node temp = head;
List< int > list = new List< int >();
while (temp != null ) {
list.Add(temp.key);
temp = temp.next;
}
int n = list.Count;
Random rand = new Random();
int randIndex = rand.Next(n);
Console.WriteLine(list[randIndex]);
}
public static void Main()
{
Node head = new Node(30);
head.next = new Node(3);
head.next.next = new Node(4);
head.next.next.next = new Node(20);
head.next.next.next.next = new Node(5);
printRandom(head);
}
}
|
Javascript
const val = 7;
class Node{
constructor(){
this .key = 0;
this .next = null ;
}
push(head_ref, new_key){
let new_node = new Node();
new_node.key = new_key;
new_node.next = head_ref;
head_ref = new_node;
return head_ref;
}
printRandom(head){
let temp = head;
let v = [];
while (temp != null ){
v.push(temp.key);
temp = temp.key;
}
let n = v.length;
let randIndex = Math.floor((Math.random() * (n-1)));
console.log(Math.floor(v[randIndex]/val));
}
}
n1 = new Node()
head = null
head = n1.push(head, 5)
head = n1.push(head, 20)
head = n1.push(head, 4)
head = n1.push(head, 3)
head = n1.push(head, 30)
n1.printRandom(head)
|
Complexity Analysis:
Time Complexity: O(n).
Space Complexity:O(n).
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
13 Apr, 2023
Like Article
Save Article