Saturday, January 11, 2025
Google search engine
HomeData Modelling & AIPython Program For Selecting A Random Node From A Singly Linked List

Python Program For Selecting A Random Node From A Singly Linked List

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:

  1. Count the number of nodes by traversing the list.
  2. Traverse the list again and select every node with probability 1/N. The selection can be done by generating a random number from 0 to N-i for i’th 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, probabilities of other selecting other nodes is 1/N
The above solution requires two traversals of 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 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.
    (a) Generate a random number from 0 to n-1. 
        Let the generated random number is j.
    (b) If j is equal to 0 (we could choose other fixed numbers 
        between 0 to n-1), then replace result with the current node.
    (c) n = n+1
    (d) current = current->next

Below is the implementation of above algorithm.

Python




# Python program to randomly select a
# node from singly linked list
import random
 
# Node class
class Node:
 
    # Constructor to initialize the
    # node object
    def __init__(self, data):
        self.data= data
        self.next = None
 
class LinkedList:
 
    # Function to initialize head
    def __init__(self):
        self.head = None
 
    # A reservoir sampling-based function
    # to print a random node from a
    # linked list
    def printRandom(self):
 
        # If list is empty
        if self.head is None:
            return
 
        if self.head and not self.head.next:
           print "Randomly selected key is %d" %(self.head.data)
 
        # Use a different seed value so that we don't get
        # same result each time we run this program
        random.seed()
 
        # Initialize result as first node
        result = self.head.data
 
        # Iterate from the (k+1)th element nth element
        # because we iterate from (k+1)th element, or
        # the first node will be picked more easily
        current = self.head.next
        n = 2
        while(current is not None):
             
            # Change result with probability 1/n
            if (random.randrange(n) == 0 ):
                result = current.data
 
            # Move to next node
            current = current.next
            n += 1
 
        print "Randomly selected key is %d" %(result)
         
    # Function to insert a new node at
    # the beginning
    def push(self, new_data):
        new_node = Node(new_data)
        new_node.next = self.head
        self.head = new_node
 
    # Utility function to print the linked
    # LinkedList
    def printList(self):
        temp = self.head
        while(temp):
            print temp.data,
            temp = temp.next
 
# Driver code
llist = LinkedList()
llist.push(5)
llist.push(20)
llist.push(4)
llist.push(3)
llist.push(30)
llist.printRandom()
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)


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 output.

How does this work? 
Let there be total N nodes in list. It is easier to understand from the last node.
The probability that the last node is result simply 1/N [For last or N’th node, we generate a random number between 0 to N-1 and make the last node as result if the generated number is 0 (or any other fixed number]
The probability that second last node is 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 probability for 3rd last node and other nodes. Please refer complete article on Select a Random Node from a Singly Linked List for more details!

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 neveropen!

Last Updated :
21 Jul, 2022
Like Article
Save Article


Previous

<!–

8 Min Read | Java

–>


Next


<!–

8 Min Read | Java

–>

RELATED ARTICLES

Most Popular

Recent Comments