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.
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();
一刷
題解:
蓄水池抽樣:
“給出一個數據流,這個數據流的長度很大或者未知。并且對該數據流中數據只能訪問一次。請寫出一個隨機選擇算法,使得數據流中所有數據被選中的概率相等。”
我們陸續(xù)收到了數據1、2和前面的例子一樣,我們只能保存一個數據,所以必須淘汰1和2中的一個。應該如何淘汰呢?不妨和上面例子一樣,我們按照二分之一的概率淘汰一個,例如我們淘汰了2。繼續(xù)讀取流中的數據3,發(fā)現數據流結束了,我們知道在長度為3的數據流中,如果返回數據3的概率為1/3,那么才有可能保證選擇的正確性。也就是說,目前我們手里有1,3兩個數據,我們通過一次隨機選擇,以1/3的概率留下數據3,以2/3的概率留下數據1.那么數據1被最終留下的概率是多少呢?
? 數據1被留下:(1/2)(2/3) = 1/3
? 數據2被留下概率:(1/2)(2/3) = 1/3
? 數據3被留下概率:1/3
這個方法可以滿足題目要求,所有數據被留下返回的概率一樣!
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
ListNode head;
Random random;
/** @param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node. */
public Solution(ListNode head) {
this.head = head;
this.random = new Random();
}
/** Returns a random node's value. */
public int getRandom() {
ListNode c = head;
int r = c.val;
for(int i=1; c.next!=null; i++){
c = c.next;
if(random.nextInt(i+1) == i) r = c.val;//nexInt(i+1) [0, i]
}
return r;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(head);
* int param_1 = obj.getRandom();
*/