382. Linked List Random Node

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.

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

Cache + nextInt, constructor O(n), getRandom O(1), S(n)

将LinkedList的所有value按顺序添加到cache中,getRandom时只需对cache.size()进行采样,返回对应的值即可。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    private List cache;
    private 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) {
        cache = new ArrayList<>();
        random = new Random();
        
        while (head != null) {
            cache.add(head.val);
            head = head.next;
        }
    }
    
    /** Returns a random node's value. */
    public int getRandom() {
        return cache.get(random.nextInt(cache.size()));
    }
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(head);
 * int param_1 = obj.getRandom();
 */

Followup: Reservoir sampling, constructor O(1), getRandom O(n), S(1)

经典的蓄水池抽样算法,从n(非常大)个元素中随机选择k个元素,对应到这道题k = 1。
优点是不需要将LinkedList全部载入内存,可以以stream的形式更新random。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    private ListNode head;
    private 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;
        random = new Random();
    }
    
    /** Returns a random node's value. */
    public int getRandom() {
        int val = head.val;
        ListNode curr = head.next;
        
        for (int i = 1; curr != null; ++i, curr = curr.next) {
            if (random.nextInt(i + 1) == 0) {   // random between [0, i]
                val = curr.val;
            }
        }
        
        return val;
    }
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(head);
 * int param_1 = obj.getRandom();
 */

你可能感兴趣的:(382. Linked List Random Node)