Given a singly linked list of unknown length, return a random node from the list by only one traversal. Each node must have the same probability of being chosen.
This problem is a popular interview question. The approach discussed below is a useful technique in data streaming applications when data is too large to fit in the memory.
We will use the reservoir sampling technique with a reservoir size equal to 1.
The algorithm consists of the following steps:
After these steps, the resulting node will be a random node chosen with equal probability from a given list. See the proof of correctness below:
Let
Let's look at the code below:
#include <random>//get random number in a given rangeint getRandomNumber(int left, int right){//C++11's random number generation facilitiesstd::uniform_int_distribution<> distrib(left, right);std::mt19937 randomGen;return distrib(randomGen);}//get random node from a given linked list in a single passListNode* getRandomNode(ListNode* head){ListNode* resultNode = head;int i = 1;ListNode* currNode = head->next;while(currNode != nullptr){int randomInd = getRandom(0, i);if(randomInd == 0)resultNode = currNode;++i;currNode = currNode->next;}return resultNode;}
Let
This proves that each node is returned with equal probability