Linked List Random Node

Updated on 04 June, 2025
Linked List Random Node header image

Problem Statement

The task is to design a class Solution that allows retrieving random values from a node in a singly-linked list with equal probability for each node. The class should be designed such that it has a constructor that takes the head of the linked list. Another key method, getRandom(), will select a node's value randomly from the linked list ensuring that each node's value has the same likelihood of being chosen. The structure emphasizes randomness and unbiased selection from the linked list's nodes.

Examples

Example 1

Input:

["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"]
[[[1, 2, 3]], [], [], [], [], []]

Output:

[null, 1, 3, 2, 2, 3]

Explanation:

Solution solution = new Solution([1, 2, 3]);
solution.getRandom(); // return 1
solution.getRandom(); // return 3
solution.getRandom(); // return 2
solution.getRandom(); // return 2
solution.getRandom(); // return 3
Each call to getRandom() should return either 1, 2, or 3 with equal probability.

Constraints

  • The number of nodes in the linked list will be in the range [1, 10^4].
  • -10^4 <= Node.val <= 10^4
  • At most 10^4 calls will be made to getRandom.

Approach and Intuition

Given the challenge to equally likely select a random node from a singly-linked list, a straightforward approach may not work due to the lack of direct access to list nodes by indices as available in arrays. This requirement brings about the necessity for a fair and random selection mechanism for linked list nodes. The getRandom() function, when called, must randomly return any node's value from the entire linked list with uniform selection probability. Let's understand with stages:

  1. Initialization:

    • Upon initializing with the Solution class constructor, store the head of the linked list.
  2. Random Node Selection:

    • Utilize the Reservoir Sampling algorithm for optimal results especially when linked list length is unknown or extremely large.
    • Traverse through the linked list starting from the head.
    • For each node, decide whether it replaces a previously chosen node in our 'reservoir' (initially the first node is chosen).
    • The probability of keeping the current node value becomes 1/k where k is the current node's index in the list + 1 (considering 1-based index).

    For example, as we advance through each node:

    • The first node gets selected with a probability of 1 (since it’s the only one).
    • For the second node, there’s a 1/2 chance it replaces the first node as the chosen node.
    • For the third node, it has a 1/3 chance, and so forth.
    • This method ensures that by the end of the list, each node has had an equal opportunity to be chosen.
  3. Return Value:

    • After completing the traversal with the reservoir sampling method applied, the value stored as the chosen node will be returned each time getRandom() is called.

This approach adheres to the constraint of each node possessing an equal probability of being chosen, given the lack of upfront knowledge about the length of the list or needing to go past the list multiple times which could be computationally expensive. The randomness is maintained uniformly across the nodes by the nature of the sampling method.

Solutions

  • Java
  • Python
java
class Solution {
    private ListNode listHead;

    public Solution(ListNode listHead) {
        this.listHead = listHead;
    }

    public int getRandom() {
        int count = 1, selectedValue = 0;
        ListNode currentNode = this.listHead;
        while (currentNode != null) {
            if (Math.random() < 1.0 / count)
                selectedValue = currentNode.val;
            count += 1;
            currentNode = currentNode.next;
        }
        return selectedValue;
    }
}

The Java solution for the "Linked List Random Node" facilitates the random selection of a node's value from a singly linked list. In this approach, you initialize the solution class with the head of a linked list. The getRandom() method then iteratively selects a node's value based on a random selection process.

  • Initialize the Solution class with the linked list's head.

  • Use the getRandom() method to select a node value randomly:

    • Set the initial count to 1 and initialize selectedValue.
    • Traverse through the linked list starting from the head node.
    • For each node, decide whether to update the selectedValue based on the result of Math.random() < 1.0 / count.
    • Increase the count by 1 after considering each node.
    • Continue traversing until all nodes are visited.

This implementation uses a reservoir sampling technique to ensure that each node's value has an equal probability of being chosen, regardless of the linked list's size. Use Math.random() to generate a random number which determines the probability of a node’s selection.

python
class Solution:
    def __init__(self, start_node: ListNode):
        self.start_node = start_node

    def pickRandom(self) -> int:
        count = 1
        selected_value = 0
        node = self.start_node

        while node:
            if random.random() < 1 / count:
                selected_value = node.val
            node = node.next
            count += 1
        return selected_value

The solution provided outlines a Python class Solution designed to select a random node from a linked list.

  • The class is initiated with a start_node, which represents the head of the linked list.
  • It includes the method pickRandom(), which returns the value of a randomly chosen node from the linked list using a probability technique known as Reservoir Sampling.

Here’s a stepwise breakdown of the pickRandom() method:

  1. Initialize the count to 1 which helps in determining the probability for selecting each node.
  2. Initialize selected_value to 0, which will store the node value that is eventually selected.
  3. Traverse through the linked list starting from the start_node.
  4. Use random.random() to generate a random number. If this number is less than 1/count, update selected_value to the current node's value.
  5. Increment the count and move to the next node in the list using node = node.next.
  6. By the end of the traversal, selected_value contains the value of the randomly selected node, which gets returned.

This algorithm ensures every node has an equal probability of being chosen, despite the linked list's size not being known in advance.

Comments

No comments yet.