链表
链表 [Linked List]:链表是由一组不必相连【不必相连:可以连续也可以不连续】的内存结构 【节点】,按特定的顺序链接在一起的抽象数据类型。
链表常用的有 3 类: 单链表、双向链表、循环链表。
单链表
单链表 [Linked List]:由各个内存结构通过一个 Next 指针链接在一起组成,每一个内存结构都存在后继内存结构【链尾除外】,内存结构由数据域和 Next 指针域组成。
双向链表
双向链表 [Double Linked List]:由各个内存结构通过指针 Next 和指针 Prev 链接在一起组成,每一个内存结构都存在前驱内存结构和后继内存结构【链头没有前驱,链尾没有后继】,内存结构由数据域、Prev 指针域和 Next 指针域组成。
循环链表
单向循环链表 [Circular Linked List] : 由各个内存结构通过一个指针 Next 链接在一起组成,每一个内存结构都存在后继内存结构,内存结构由数据域和 Next 指针域组成。
双向循环链表 [Double Circular Linked List] : 由各个内存结构通过指针 Next 和指针 Prev 链接在一起组成,每一个内存结构都存在前驱内存结构和后继内存结构,内存结构由数据域、Prev 指针域和 Next 指针域组成。
leetcode 142
代码实现
以下是我个人根据集合实现的,时间复杂度为O(n)。
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
s = set()
while head:
if head in s:
return head
s.add(head)
head = head.next
return None
下面是最佳实践,空间复杂度为O(1),时间复杂度与上面一样。
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
try:
fast = head.next
slow = head
while fast is not slow:
fast = fast.next.next
slow = slow.next
except:
return None
slow = slow.next
while slow is not head:
slow = slow.next
head = head.next
return head
最佳实践的思路会有一点抽象,我从leetcode的讨论中截了一段解释
前面的其实还好理解,主要是fast跟上slow后,slow继续走下去,补全圆圈(即回到E点)所走的路程为 nL-D,直到某一圈恰好等于head所走的H,此时两者会在E点相遇。
leetcode 206
代码实现
这是普通的遍历方法:
class Solution:
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
prev = None
late = None
while head:
prev = head
head = head.next
prev.next = late
late = prev
return late
下面的是递归方法:
class Solution:
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or not head.next:
return head
p = self.reverseList(head.next)
head.next.next = head
head.next = None
return p
说实话递归方法实在是抽象,我试着画了一幅示意图来帮助理解: