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();
水塘抽样原理
总结:在取第n个数据的时候,我们生成一个0到1的随机数p,如果p小于1/n,保留第n个数。大于1/n,继续保留前面的数。直到数据流结束,返回此数
补充: c++ 标准库中的rand()函数。C++标准函数库提供一随机数生成器rand,返回0-RAND_MAX之间均匀分布的伪随机整数。 RAND_MAX必须至少为32767。rand()函数不接受参数,默认以1为种子(即起始值)。
rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数。 这样,如果你要产生0~10的10个整数,可以表达为: int N = rand()%11; 这样,N的值就是一个0~10的随机数,如果要产生1~10,则是这样: int N = 1+rand() % 10; 总结来说,可以表示为: a + rand()%n 其中的a是起始值,n是整数的范围。 a + rand() % (b-a+1) 就表示 a~b之间的一个随机数
在每一个数的时候我们只要按照随机一个是否是i的倍数即可决定是否取当前数即可.
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: /** @param head The linked list's head. Note that the head is guaranteed to be not null, so it contains at least one node. */ Solution(ListNode* head) { p = head; } /** Returns a random node's value. */ int getRandom() { ListNode *tem = p; int val = p -> val; for(int i = 1; tem; i++) { if(rand() % i == 0) val = tem->val; // 如果产生的值为i,此时返回 tem = tem -> next; } return val; } private: ListNode *p; }; /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(head); * int param_1 = obj.getRandom(); */