0382. 链表随机节点
文章目录
- 题目链接
- 题目描述
- 解题思路
- 参考代码
- 参考代码(水塘抽样:O(1) 空间)
- 复杂度分析
题目链接
https://leetcode.cn/problems/linked-list-random-node/
题目描述
给定一个单链表,实现一个类以等概率返回链表中的一个节点值。
解题思路
- 你当前实现:预先遍历链表把所有值存入数组,getRandom 时用等概率随机索引返回。
- 优点:实现简单,查询 O(1)。
- 缺点:额外空间 O(n);当链表极大时不友好。
- 进阶(水塘抽样 Reservoir Sampling):
- 仅一次遍历,不使用额外数组即可等概率返回任一节点。
- 思路:遍历到第 i 个节点时,以 1/i 的概率选择它替代当前答案。
参考代码
/*** 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 final List<Integer> list = new ArrayList<>();private final Random rand = new Random();public Solution(ListNode head) {while (head != null) {list.add(head.val);head = head.next;}}public int getRandom() {int idx = rand.nextInt(list.size()); // 均匀分布 [0, size)return list.get(idx);}
}
参考代码(水塘抽样:O(1) 空间)
class Solution {private final ListNode head;private final Random rand = new Random();public Solution(ListNode head) {this.head = head;}public int getRandom() {int ans = -1;int i = 0;for (ListNode cur = head; cur != null; cur = cur.next) {i++;// 以 1/i 的概率选择当前节点if (rand.nextInt(i) == 0) {ans = cur.val;}}return ans;}
}
复杂度分析
- 数组法:时间复杂度 O(n) 预处理 + O(1) 查询;空间复杂度 O(n)。
- 水塘抽样:每次查询 O(n) 遍历;空间复杂度 O(1)。
