链接
leetcode-24
题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
dummy_head = ListNode(next=head)
current = dummy_head
# 必须有cur的下一个和下下个才能交换,否则说明已经交换结束了
while current.next and current.next.next:
temp = current.next # 防止节点修改
temp1 = current.next.next.next
current.next = current.next.next
current.next.next = temp
temp.next = temp1
current = current.next.next
return dummy_head.next
链接
leetcode-19
题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
一开始想过采用两次循环,先计数,再尝试用之前题目中写过的删除index的方式进行删除。但是总是会在边界情况处理不好。
贴上一个不正确的答案,只能过190/208(这就是我在考场上能写出的样子吧……)
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummyNode = ListNode(next=head)
size = 0
current = dummyNode.next
while current.next:
current = current.next
size += 1
if n<0 or n>size+1 or size==0:
return
current = dummyNode.next
for i in range(size-n):
current = current.next
current.next = current.next.next
return dummyNode.next
学习采用快慢指针的方法解决该问题。
可以参考labuladong的双指针技巧秒杀七道链表题目
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 创建一个虚拟节点,并将其下一个指针设置为链表的头部
dummy_head = ListNode(0, head)
# 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点
slow = fast = dummy_head
# 快指针比慢指针快 n+1 步
for i in range(n+1):
fast = fast.next
# 快指针到达链表的末尾时,循环结束
while fast:
slow = slow.next
fast = fast.next
# 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点
slow.next = slow.next.next
return dummy_head.next
链接
leetcode-160
题目
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
lenA, lenB = 0, 0
cur = headA
while cur:
cur = cur.next
lenA += 1
cur = headB
while cur:
cur = cur.next
lenB += 1
curA, curB = headA, headB
if lenA > lenB:
curA, curB = curB, curA
lenA, lenB = lenB, lenA
for i in range(lenB - lenA):
curB = curB.next
while curA:
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
return None
链接
leetcode-142
题目
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
def detectCycle(head: ListNode) -> ListNode:
fast = slow = head
# 快指针走两步,慢指针走一步
# 如果快指针追上了慢指针,说明有环
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
# 否则,没有环
if not fast or not fast.next:
return None
# 判断开始入环的第一个节点
slow = head
while slow != fast:
fast = fast.next
slow = slow.next
return slow
判断环起点的思路详见142.环形链表II
需要整理!
另外,运用集合,使得这道题目的难度瞬间降低了一个级别:
# 集合法
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
visited = set()
while head:
if head in visited:
return head
visited.add(head)
head = head.next
return None