Leetcode 382 链表随机节点 蓄水池抽样与随机数

  概率问题,蓄水池抽样与生成随机数都可以解决。蓄水池抽样适合数据量巨大且不知道数组集合大小时的随机抽样,因为是线性扫描每一个元素进行抽样,空间复杂度为 O(1) ,时间复杂度为O(n)。

  蓄水池抽样算法:

复制代码
class Solution {
        ListNode head;
        Random random;

        public Solution(ListNode head) {
            this.head = head;
            random = new Random(0);
        }

        public final int getRandom() {
            Integer an = null;
            int point = 1;
            ListNode node = head;
            while (node != null) {
                if (an == null) {
                    an = node.val;
                } else {
                    int ran = random.nextInt(point);
                    if (ran < 1) {
                        an = node.val;
                    }
                }
                node = node.next;
                point++;
            }
            return an == null ? 0 : an;
        }
    }
复制代码

 

  随机数抽样,需要预先知道集合大小:

复制代码
class Solution {
        private ListNode head = null;
        private int size = 0;
        Random random = new Random(0);

        public Solution(ListNode head) {
            if (head != null) {
                this.head = head;
                ListNode node = head;
                while (node != null) {
                    node = node.next;
                    this.size++;
                }
            }
        }

        /**
         * Returns a random node's value.
         */
        public final int getRandom() {
            if (size <= 1) {
                return head.val;
            }
            int currentRandom = random.nextInt(size);
            return getNode(currentRandom).val;
        }

        private final ListNode getNode(int point) {
            if (point >= this.size) {
                return null;
            }
            ListNode an = head;
            while (point > 0) {
                an = an.next;
                point--;
            }
            return an;
        }

    }
复制代码

  JS 蓄水池算法:

复制代码
var Solution = function (head) {
    this.head = head;
};

/**
 * Returns a random node's value.
 * @return {number}
 */
Solution.prototype.getRandom = function () {
    let point = 1;
    let an = -1;
    let node = this.head;
    while (node != null) {
        if (an == -1) {
            an = node.val;
        } else {
            let ran = parseInt(Math.random() * (point));
            if (ran < 1) {
                an = node.val;
            }
        }
        node = node.next;
        point++;
    }
    return an;
};
复制代码

 

posted @   牛有肉  阅读(276)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示