题目

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:

  1. // Init a singly linked list [1,2,3].
  2. ListNode head = new ListNode(1);
  3. head.next = new ListNode(2);
  4. head.next.next = new ListNode(3);
  5. Solution solution = new Solution(head);
  6. // getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning.
  7. solution.getRandom();

题意

思路

最简单的方法是直接遍历链表,把值全部存到List中,最后随机下标即可。

官方解答还有一种神奇的水塘采样方法。


代码实现

Java

List存储

  1. class Solution {
  2. private List<Integer> list = new ArrayList<>();
  3. private Random random = new Random();
  4. /** @param head The linked list's head.
  5. Note that the head is guaranteed to be not null, so it contains at least one node. */
  6. public Solution(ListNode head) {
  7. while (head != null) {
  8. list.add(head.val);
  9. head = head.next;
  10. }
  11. }
  12. /** Returns a random node's value. */
  13. public int getRandom() {
  14. int index = random.nextInt(list.size());
  15. return list.get(index);
  16. }
  17. }

水塘采样

  1. class Solution {
  2. private ListNode head;
  3. /** @param head The linked list's head.
  4. Note that the head is guaranteed to be not null, so it contains at least one node. */
  5. public Solution(ListNode head) {
  6. this.head = head;
  7. }
  8. /** Returns a random node's value. */
  9. public int getRandom() {
  10. ListNode chosen = null;
  11. int count = 1;
  12. ListNode cur = head;
  13. while (cur != null) {
  14. if (Math.random() < 1.0 / count) {
  15. chosen = cur;
  16. }
  17. count++;
  18. cur = cur.next;
  19. }
  20. return chosen.val;
  21. }
  22. }