leetcode每日一题382. 链表随机节点 链表+随机数使用 或 蓄水池抽样 小学抽卡问题

📖本篇内容:leetcode每日一题382. 链表随机节点 链表+随机数使用 或 蓄水池抽样 小学抽卡问题

📑 文章专栏:leetcode每日一题《打卡日常》

📆 最近更新:2022年1月15日 leetcode每日一题1716. 计算力扣银行的钱 数学问题 等差数列 这不是高中的知识么 + 逻辑推理

🙊个人简介:一只二本院校在读的大三程序猿,本着注重基础,打卡算法,分享技术作为个人的经验总结性的博文博主,虽然可能有时会犯懒,但是还是会坚持下去的,如果你很喜欢博文的话,建议看下面一行~(疯狂暗示QwQ)

🌇 点赞 👍 收藏 ⭐留言 📝 一键三连 关爱程序猿,从你我做起

写在前面

蹦撒卡拉耶~小付闪亮登场,可能因为今天一直在搞MVC的底层源码,给我干的有点懵逼懵逼的状态,想睡睡不着,坐也不是站也不是,唯有刷题解千愁,解完能睡觉QwQ,今天的题我第一遍做的时候还以为是我看错了,只需要简单的这样,然后那样就可以了,话不多说,来看看小付的刷题之旅!

题目

  1. 链表随机节点

给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 被选中的概率一样 。
实现 Solution 类:
Solution(ListNode head) 使用整数数组初始化对象。
int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等

示例

示例1:

输入
["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"]
[[[1, 2, 3]], [], [], [], [], []]
输出
[null, 1, 3, 2, 2, 3]

解释
Solution solution = new Solution([1, 2, 3]);
solution.getRandom(); // 返回 1
solution.getRandom(); // 返回 3
solution.getRandom(); // 返回 2
solution.getRandom(); // 返回 2
solution.getRandom(); // 返回 3
// getRandom() 方法应随机返回 1、2、3中的一个,每个元素被返回的概率相等。

提示

链表中的节点数在范围 [1, 10^4] 内
-10^4 <= Node.val <= 10^4
至多调用 getRandom 方法 10^4 次

思路

将每个节点置于链表当中,依次将节点加入到链表通过随机函数获取链表的值。

代码实现

class Solution {
	//创建链表用于存储节点
     List<ListNode> list = new LinkedList<>();
    Random random = new Random();
    public Solution(ListNode head) {
    //遍历将每个节点加入到链表当中
        ListNode node = head;
        while (node != null) {
            list.add(node);
            node = node.next;
        }
    }

    public int getRandom() {
    //通过随机获取节点获取值
        return list.get(random.nextInt(list.size())).val;
    }
}

执行结果

在这里插入图片描述

代码优化

当数据过多时,链表空间无法存储所有数据那该如何解决这种问题呢?

蓄水池抽象算法:N代表总数字个数

1、当我们需要从一堆数字中抽取一个数字时,那么它被抽取的概率一定是 1/N

每次随机获得的这个数字替换掉所要抽取的数字保证每一次抽出的数字概率

都是 1/N

2、当我们要冲一堆数字中 抽取多个数字m个时 ,那么每个数字被抽到的概率就变为了 m/N ,所以对于前面的 m 个 数字 就无须替换全部进行保留,当 抽取数字 数目 大于第m个时 ,就要通过替换之前 m 个中的 一个数字 进行抽取 保证每个数字抽到的概率相同。

代码实现

class Solution {
    ListNode head;
    public Solution(ListNode head) {
        this.head = head;
    }
    
    public int getRandom() {
        // 定义结果变量,存储随机获取的结果值
        int result = 0;
        // 定义一个变量i,用于记录遍历到了第几个节点
        int i = 0;
        ListNode cur = head;
        // 循环遍历链表
        while (cur != null) {
            i++;
            // 取随机数rand 范围 [1, i]
            int rand = new Random().nextInt(i) + 1;
            // 因为rand最小值为1,这个边界只能取rand == 1
            if (rand == 1) {
                result = cur.val;
            }
            // 指针往后移动,遍历下一个节点
            cur = cur.next;
        }

        // 返回获取值结果
        return result;
    }
}

写在最后

今天是2022-01-16小付坚持打卡了哦~

简单的数据结构的链表问题

对数学算法进行了考察

周赛也要加油哦~

冲冲冲!

最后

每天进步点 每天收获点

愿诸君 事业有成 学有所获

如果觉得不错 别忘啦一键三连哦~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alascanfu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值