[LeetCode] 382. Linked List Random Node 鏈表隨機節點


 

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 Solution {
public:
    Solution(ListNode* head) {
        len = 0;
        ListNode *cur = head;
        this->head = head;
        while (cur) {
            ++len;
            cur = cur->next;
        }
    }
    int getRandom() {
        int t = rand() % len;
        ListNode *cur = head;
        while (t) {
            --t;
            cur = cur->next;
        }
        return cur->val;
    }
private:
    int len;
    ListNode *head;
};

 

Follow up 中說鏈表可能很長,我們沒法提前知道長度,這里用到了著名了 水塘抽樣 Reservoir Sampling 的思路,由於限定了 head 一定存在,所以先讓返回值 res 等於 head 的節點值,然后讓 cur 指向 head 的下一個節點,定義一個變量i,初始化為2,若 cur 不為空則開始循環,在 [0, i - 1] 中取一個隨機數,如果取出來0,則更新 res 為當前的 cur 的節點值,然后此時i自增一,cur 指向其下一個位置,這里其實相當於維護了一個大小為1的水塘,然后隨機數生成為0的話,交換水塘中的值和當前遍歷到的值,這樣可以保證每個數字的概率相等,參見代碼如下:

 

解法二:

class Solution {
public:
    Solution(ListNode* head) {
        this->head = head;
    }
    int getRandom() {
        int res = head->val, i = 2;
        ListNode *cur = head->next;
        while (cur) {
            int j = rand() % i;
            if (j == 0) res = cur->val;
            ++i;
            cur = cur->next;
        }
        return res;
    }
private:
    ListNode *head;
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/382

 

類似題目:

Random Pick Index

 

參考資料:

https://leetcode.com/problems/linked-list-random-node/

https://leetcode.com/problems/linked-list-random-node/discuss/85662/Java-Solution-with-cases-explain

https://leetcode.com/problems/linked-list-random-node/discuss/85659/Brief-explanation-for-Reservoir-Sampling

https://leetcode.com/problems/linked-list-random-node/discuss/85701/O(n)-Time-and-O(1)-Space-Java-Solution

https://leetcode.com/problems/linked-list-random-node/discuss/85690/using-reservoir-sampling-o1-space-on-time-complexityuff0cc

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM