📖本篇内容:leetcode每日一题382. 链表随机节点 链表+随机数使用 或 蓄水池抽样 小学抽卡问题
📑 文章专栏:leetcode每日一题《打卡日常》
📆 最近更新:2022年1月15日 leetcode每日一题1716. 计算力扣银行的钱 数学问题 等差数列 这不是高中的知识么 + 逻辑推理
🙊个人简介:一只二本院校在读的大三程序猿,本着注重基础,打卡算法,分享技术作为个人的经验总结性的博文博主,虽然可能有时会犯懒,但是还是会坚持下去的,如果你很喜欢博文的话,建议看下面一行~(疯狂暗示QwQ)
🌇 点赞 👍 收藏 ⭐留言 📝 一键三连 关爱程序猿,从你我做起
写在前面
蹦撒卡拉耶~小付闪亮登场,可能因为今天一直在搞MVC的底层源码,给我干的有点懵逼懵逼的状态,想睡睡不着,坐也不是站也不是,唯有刷题解千愁,解完能睡觉QwQ,今天的题我第一遍做的时候还以为是我看错了,只需要简单的这样,然后那样就可以了,话不多说,来看看小付的刷题之旅!
题目
- 链表随机节点
给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 被选中的概率一样 。
实现 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小付坚持打卡了哦~
简单的数据结构的链表问题
对数学算法进行了考察
周赛也要加油哦~
冲冲冲!
最后
每天进步点 每天收获点
愿诸君 事业有成 学有所获
如果觉得不错 别忘啦一键三连哦~