文章目录
1. 链表反转
1.1 完全反转
- 迭代
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
p = head
pre = None
while p:
aft = p.next
p.next = pre
pre = p
p = aft
return pre
- 递归
递归法就记一张图 — 递归反转链表的一部分
1->2->3->^
1->2<-3
|->^
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head is None or head.next is None:
return head
last = self.reverseList(head.next)
head.next.next = head
head.next = None
return last
1.2 部分反转
结合对1.1
递归法的学习,将后继None
替换成本场景的successor
,我们看看commits:
class Solution:
successor = None
def reverseN(self, head: ListNode, N=inf) -> ListNode:
if N == 1 or head is None or head.next is None:
self.successor = head.next
return head
last = self.reverseN(head.next, N - 1)
head.next.next = head
head.next = self.successor
return last
def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
if left == 1:
return self.reverseN(head, right)
head.next = self.reverseBetween(head.next, left - 1, right - 1)
return head
1.3 K个一组反转
class Solution:
def reverse(self, a, b):
# 相当于左开右闭,例如k=2,
# 1->2->3
# a↑ b↑
# 最后返回是的 2->1->∅
pre = None
p = a
while p != b:
aft = p.next
p.next = pre
pre = p
p = aft
return pre
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
a = b = head
# 循环体写错 (老错误)
for _ in range(k):
if b is None:
return head
b = b.next
new_head = self.reverse(a, b)
# 把 a 写成了 new_head
a.next = self.reverseKGroup(b, k) # b 写错 (老错误)
return new_head
2. 链表相交 + 链表找环
本文还有大量没有考虑到的情况,可以看相关博客
数据结构及算法:链表相关(如何判断单链表是否存在环、找出入环点、链表相交等问题)
插图出自"求两个链表的相交点(含链表带环情况)",本文2.1 普通相交讨论case 0
,2.2 普通有环讨论case 1
,2.3 相交有环讨论case 2
, case 3
。2.3 相交有环对4种情况都做了总结,考虑了所有边界条件。
2.1 普通相交
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
a, b = headA, headB
while a != b:
a = a.next if a else headB
b = b.next if b else headA
return a
class Solution:
def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
a, b = p, q
while a != b:
a = a.parent if a else q
b = b.parent if b else p
return a
2.2 普通有环
2.2.1 判断是否有环
class Solution:
def hasCycle(self, head: ListNode) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
2.2.2 找出环的入口
如果快慢指针是在写不出来,可以用hash表来写,就是空间复杂度会变成 O ( N ) O(N) O(N)
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
vis = {
}
p = head
while p:
id_ = id(p)
if id_ in vis: