题目链接
https://leetcode.com/problems/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();
思路方法
思路一
直观的思路:在初始化时统计链表长度,每次随机返回节点时,在该长度内随机出一个索引,从链表头开始找到该索引对应的值即可。空间复杂度O(1)。
代码
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def __init__(self, head):
"""
@param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node.
:type head: ListNode
"""
self.head = head
self.length = 0
while head:
self.length += 1
head = head.next
def getRandom(self):
"""
Returns a random node's value.
:rtype: int
"""
pointer = self.head
index = random.randint(0, self.length - 1)
for i in xrange(index):
pointer = pointer.next
return pointer.val
# Your Solution object will be instantiated and called as such:
# obj = Solution(head)
# param_1 = obj.getRandom()
思路二
如果不考虑follow up的要求,可以将所有元素先保存到数组,那么在随机取数时效率会高的多,但空间复杂度O(n)。
代码
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def __init__(self, head):
"""
@param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node.
:type head: ListNode
"""
self.vals = []
while head:
self.vals.append(head.val)
head = head.next
def getRandom(self):
"""
Returns a random node's value.
:rtype: int
"""
return self.vals[random.randint(0, len(self.vals)-1)]
# Your Solution object will be instantiated and called as such:
# obj = Solution(head)
# param_1 = obj.getRandom()
思路三
蓄水池采样(Reservoir Sampling)算法。蓄水池采样解决的是从N个数中等概率的取出k个数的问题,本题特殊情况k=1。
代码
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def __init__(self, head):
"""
@param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node.
:type head: ListNode
"""
self.head = head
def getRandom(self):
"""
Returns a random node's value.
:rtype: int
"""
node, n = self.head, 0
res = 0
while node:
if random.randint(0, n) == 0:
res = node.val
node, n = node.next, n+1
return res
# Your Solution object will be instantiated and called as such:
# obj = Solution(head)
# param_1 = obj.getRandom()
PS: 写错了或者写的不清楚请帮忙指出,谢谢!
转载请注明:http://blog.youkuaiyun.com/coder_orz/article/details/52398164