Given a singly linked list, return a random node's value from the linked list. Each node must have thesame probabilityof being chosen.
Follow up:
What if the linked list is extremely large and its length is unknown to you? Could you solve this efficiently without using extra space?
Example:
// Init a singly linked list [1,2,3].
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution(head);
// getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning.
solution.getRandom();
Solution
Reservoir Sampling
O(1) space, O(n) time
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */classSolution {privateRandom rand;privateListNode head; /** @param head The linked list's head. Note that the head is guaranteed to be not null, so it contains at least one node. */publicSolution(ListNode head) {this.head= head; rand =newRandom(); } /** Returns a random node's value. */publicintgetRandom() {int result =-1;ListNode p = head;int count =0;while (p !=null) { count++;if (rand.nextInt(count) <1) { result =p.val; } p =p.next; }return result; }}/** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(head); * int param_1 = obj.getRandom(); */
A more generic one for k > 1 reservoir sampling
publicclassSolution {privateListNode head;privateRandom rand; /** @param head The linked list's head. Note that the head is guaranteed to be not null, so it contains at least one node. */publicSolution(ListNode head) {this.head= head;this.rand=newRandom(); } /** Returns a random node's value. */publicintgetRandom() {int k =1;ListNode node =this.head;int res =node.val;int i =0;ArrayList<Integer> reservoir =newArrayList<Integer>();while (i < k && node !=null) {reservoir.add(node.val); node =node.next; i++; } i++; // i == k => i == k+1while (node !=null) {int j =rand.nextInt(i);if (j < k) {reservoir.set(j,node.val); } i++; node =node.next; }returnreservoir.get(0);// or return reservoir when k > 1; }}
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */classSolution { /** @param head The linked list's head. Note that the head is guaranteed to be not null, so it contains at least one node. */publicSolution(ListNode head) { root = head;int count =0;ListNode p = root;while (p !=null) { p =p.next; count++; } length = count; } /** Returns a random node's value. */publicintgetRandom() {Random rand =newRandom();int n =rand.nextInt(length);ListNode p = root;while (n-->0) { p =p.next; }returnp.val; }privateint length;privateListNode root;}/** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(head); * int param_1 = obj.getRandom(); */