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();

蓄水池算法,要是我肯定是想不出来的,所以不会做,网上看到的代码。

代码如下:

/*
class ListNode 
 {
      int val;
      ListNode next;
      ListNode(int x) { val = x; }
 }
 */

/*
 * 这道题用到的就是这个蓄水池算法。看代码的时候就简单多了。
 */
class Solution 
{
    ListNode head;
    public Solution(ListNode head) 
    {
        this.head = head;
    }

    public int getRandom() 
    {
        Random random = new Random();
        int result = head.val;
        ListNode currNode = head;
        for(int i=1; currNode.next!=null; i++) 
        {
            currNode = currNode.next;
            if((random.nextInt(i + 1)) == i)
            {
                result = currNode.val;
            }
        }
        return result;
    }
}

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

下面是C++做法,

这道题给了我们一个链表,让我们随机返回一个节点,那么最直接的方法就是先统计出链表的长度,然后根据长度随机生成一个位置,然后从开头遍历到这个位置即可,

可以和这道题leetcode 384. Shuffle an Array 数组随机洗牌一起学习

代码如下:

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>

using namespace std;


/*
struct ListNode 
{
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
};
*/


class Solution 
{
public:

    int len;
    ListNode *head;


    /** @param head The linked list's head. Note that the head is guanranteed to be not null, so it contains at least one node. */
    Solution(ListNode* head) 
    {
        len = 0;
        ListNode *cur = head;
        this->head = head;
        while (cur) 
        {
            ++len;
            cur = cur->next;
        }
    }

    /** Returns a random node's value. */
    int getRandom() 
    {
        int t = rand() % len;
        ListNode *cur = head;
        while (t) 
        {
            --t;
            cur = cur->next;
        }
        return cur->val;
    }
};