蓄水池通用随机算法 Java

LeetCode例题:

给定一个单链表,随机选择链表的一个节点,并返回相应的节点值。保证每个节点被选的概率一样。

进阶:
如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现?

示例:

// 初始化一个单链表 [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()方法应随机返回1,2,3中的一个,保证每个元素被返回的概率相等。
solution.getRandom();

 

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

 

 

链表结构类

public class ListNode {
      int val;
      ListNode next;
      ListNode() {}
      ListNode(int val) { this.val = val; }
      ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

 测试&&方法类

import java.util.Random;

public class LeetCode {
    public ListNode listNode;
    LeetCode(ListNode listNode) {
        this.listNode = listNode;
    }
    int getRandom() {
        int i = 2;
     Random random = new Random(); 
int rand = this.listNode.val; ListNode listNode = this.listNode.next; while (null != listNode) { if (random.nextInt(i) == 0) { rand = listNode.val; } i++; listNode = listNode.next; } return rand; } public static void main(String[] args) { ListNode head = new ListNode(1); head.next = new ListNode(2); head.next.next = new ListNode(3); LeetCode leetCode = new LeetCode(head); System.out.println(leetCode.getRandom()); } }

原理是

  链表元素只有一个时候 不会进入if,所以第一个概率是1/n(n=1)

  当为2个的时候,进入if,随机数会在0,1之间生成,所以每一个概率是1/n

  当为3个的时候,进入2次if,想要方法返回第一个,第一次进if的时候必须是随机到1,概率为1/2,第二次进入if时候,必须随机到1或者2,概率是2/3,然后相乘 1/2 * 2/3 = 1/3(1/n)

  其他以此类推 每个元素的概率都是1/n,这样的时间复杂度是O(n)只遍历一次,就可以取出链表中的元素,如果按照先遍历列表,再随机到数后再去遍历会导致遍历两次,且时间复杂度最坏情况是O(n^2)

蓄水池通用随机算法 Java

上一篇:js基础---数组去重


下一篇:位或例题Java 暴力法和前缀异或法