Description
Given a singly linked list, return a random node’s value from the linked list. Each node must have the same probability of being chosen.
Implement the Solution
class:
Solution(ListNode head)
Initializes the object with the head of the singly-linked listhead
.int getRandom()
Chooses a node randomly from the list and returns its value. All the nodes of the list should be equally likely to be chosen.
Examples:
Example 1:
Input
["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"]
[[[1, 2, 3]], [], [], [], [], []]
Output
[null, 1, 3, 2, 2, 3]
Solution in Python
Solution Design
- Initialization:
- Store the
head
of the linked list. - This allows us to access and iterate over the list from the beginning each time we call
getRandom
.
- Store the
- getRandom Method:
- We perform a single traversal of the list using a reservoir sampling approach to pick a random node with equal probability.
- As we traverse each node, we decide whether to select it as our random node based on a progressively smaller probability:
- For the i-th node, we select it with a probability of 1\i.
- This approach guarantees that each node has an equal chance of being selected, regardless of the list’s length.
Python
class Solution:
def __init__(self, head: Optional[ListNode]):
# Initialize the Solution with the head of the linked list
self.head = head
def getRandom(self) -> int:
# Initialize variables for reservoir sampling
reservoir = -1 # Placeholder for the value of the selected node
current = self.head # Start at the head of the list
n = 0 # Tracks the index of the current node for probability calculation
# Traverse the linked list
while current:
n += 1 # Increment the count of nodes seen so far
# Decide to replace the reservoir with current node's value with probability 1/n
if random.randint(1, n) == 1:
reservoir = current.val
# Move to the next node
current = current.next
return reservoir # Return the value of the selected node
Explanation of getRandom
:
- Initialization:
reservoir
: Holds the value of the randomly chosen node, initially set to-1
(or any placeholder value).current
: A pointer to traverse the list starting fromhead
.n
: Tracks the position of the current node for determining selection probability.
- Reservoir Sampling Logic:
- For each node visited:
- Increment
n
to reflect the total nodes encountered. - Use
random.randint(1, n)
to simulate a probability of 1/n. If the result is1
, replacereservoir
with the current node’s value.
- Increment
- Continue until reaching the end of the list, at which point
reservoir
holds the value of the randomly chosen node.
- For each node visited:
Solution in C++
C++
class Solution {
private:
ListNode* head; // Head of the linked list
public:
// Constructor to initialize the Solution with the head of the linked list.
Solution(ListNode* head) {
this->head = head;
}
// Function to get a random node's value using Reservoir Sampling.
int getRandom() {
int result; // To store the value of the selected node
int count = 1; // Counter to track the number of nodes traversed
ListNode* current = head; // Start from the head of the list
// Traverse the linked list
while (current != nullptr) {
// Reservoir sampling probability logic:
// Replace result with current node's value with probability 1/count.
if (rand() % count == 0) {
result = current->val; // Select the current node's value
}
count++; // Increment the node counter
current = current->next; // Move to the next node
}
return result; // Return the randomly selected node's value
}
};
Solution in Javascript
JavaScript
var Solution = function(head) {
// Initialize the Solution class with the head of the linked list.
this.head = head;
};
/**
* Chooses a random node from the linked list and returns its value.
* Each node must have the same probability of being chosen.
* @return {number} - The value of the randomly chosen node
*/
Solution.prototype.getRandom = function() {
let result = null; // Variable to store the result (value of the randomly chosen node)
let current = this.head; // Start from the head of the linked list
let index = 0; // Tracks the index of the current node as we traverse the list
// Traverse the entire linked list
while (current !== null) {
// For each node, decide if it should be chosen based on its probability
// Probability of choosing the current node decreases as the index increases
if (Math.floor(Math.random() * (index + 1)) === 0) {
result = current.val; // Select the current node's value as the result
}
// Move to the next node in the list
current = current.next;
index++; // Increment the index for the next node
}
return result; // Return the value of the randomly chosen node
};
Solution in Java
Java
class Solution {
// Instance variable to hold the head of the linked list
private ListNode head;
// Random object to generate random numbers
private Random rand;
/**
* Constructor to initialize the object with the head of the singly-linked list.
* @param head the head of the linked list.
*/
public Solution(ListNode head) {
this.head = head; // Save the head of the list
this.rand = new Random(); // Initialize Random object
}
/**
* Chooses a random node's value from the linked list.
* @return the value of the randomly selected node.
*/
public int getRandom() {
int result = 0; // Variable to store the result
ListNode current = head; // Start with the head node
int count = 0; // Counter to keep track of the node index
// Traverse through the linked list
while (current != null) {
count++; // Increment node count
// Generate a random number in the range [0, count-1]
// If it's 0, update the result with the current node's value
if (rand.nextInt(count) == 0) {
result = current.val;
}
// Move to the next node
current = current.next;
}
return result; // Return the randomly selected node's value
}
}