# 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:

- Count the number of nodes by traversing the list.
- 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)` |

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 3^{rd} last node and other nodes.

Please refer complete article on Select a Random Node from a Singly Linked List for more details!