leetcode学习笔记382 Linked List Random Node

leetcode学习笔记382问题思考方法1方法2问题Linked List Random NodeGiven 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 leng
摘要由CSDN通过智能技术生成

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

思考

在不考虑follow up的情况下其实很简单. 都取出来,存在一个arraylist里面, 然后每次用随机数去取就可以了( 用java自带的random方法严格意义上说其实是伪随机数, pseudorandom number).

方法1

  • Solution()
    时间复杂度O(n).
    空间复杂度O(n).
  • getRandom()
    时间复杂度O(1).
/**
 * Definition for singly-linked list.
 * 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; }
 * }
 */
class Solution {

    private List<Integer> list = new ArrayList<Integer>();
    private Random rnd = new Random();
    
    /** @param head The linked list's head.
        Note that the head is guaranteed to be not null, so it contains at least one node. */
    public Solution(ListNode head) {
        
        while(head != null){
            list.add(head.val);
            head = head.next;
        }
        
    }
    
    /** Returns a random node's value. */
    public int getRandom() {
        return list.get(rnd.nextInt(list.size()));
    }
}

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

方法2

如果来源数据特别大, 如何在固定空间复杂度的情况下实现随机取值呢?

Reservoir Sampling (蓄水池采样). 关于蓄水池采样的详细描述以后有时间可以再补上. 这里简单只做简单说明.
原始的算法是为了解决从n个元素中随机取k个样本.

  1. 先选取从1 到k 一共k个元素作为初始样本组.
  2. 从k + 1 开始取随机数(范围 1 到k +1), 如果随机数小于K+ 1 (假设为 j), 那么用 K+ 1 位的数, 替换掉第j位的数
  3. 循环上述2的处理,直到最后一位.

为什么这样的处理能做到随机呢? 也就是让每个元素被选中的概率是相等的呢? 证明过程有时间再补充.

  • Solution()
    时间复杂度O(1).
    空间复杂度O(1).
  • getRandom()
    时间复杂度O(n).
/**
 * Definition for singly-linked list.
 * 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; }
 * }
 */
class Solution {

    private ListNode head;
    Random rnd = new Random();
    
    /** @param head The linked list's head.
        Note that the head is guaranteed to be not null, so it contains at least one node. */
    public Solution(ListNode head) {
        this.head = head;
    }
    
    /** Returns a random node's value. */
    public int getRandom() {
        int i = 1, res = this.head.val;
        ListNode cur = this.head.next;
        while(cur != null){
            if(rnd.nextInt(i + 1) == i)
                res = cur.val;
            i++;
            cur = cur.next;
        }
        return res;
    }
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(head);
 * int param_1 = obj.getRandom();
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值