代码随想录算法训练营|Day 4
Day 4
今日任务
● 24. 两两交换链表中的节点
● 19.删除链表的倒数第N个节点
● 面试题 02.07. 链表相交
● 142.环形链表II
● 总结
详细布置
24. 两两交换链表中的节点
建议先看视频
关键:建议用虚拟头结点,需要temp保存临时节点
题目链接/文章讲解/视频讲解: https://programmercarl.com/0024.两两交换链表中的节点.html
理解:想要操作两个节点,需要到这两个节点的前一个节点的位置
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy_head = ListNode(next = head)
curr = dummy_head
while curr.next != None and curr.next.next != None:
tmp = curr.next
tmp1 = curr.next.next.next
curr.next = curr.next.next
curr.next.next = tmp
tmp.next = tmp1
curr = curr.next.next
return dummy_head.next
递归版本:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
# 待翻转的两个node分别是pre和cur
pre = head
cur = head.next
next = head.next.next
cur.next = pre # 交换
pre.next = self.swapPairs(next) # 将以next为head的后续链表两两交换
return cur
19.删除链表的倒数第N个节点
建议先看视频
关键:
1.双指针的操作
2.删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点
题目链接/文章讲解/视频讲解:https://programmercarl.com/0019.删除链表的倒数第N个节点.html
方法:
快指针移动n步后,再开始移动慢指针。当快指针移动到了None,慢指针就移动到了应该被删的那个节点
操作指针要指向被删节点的前一个。因此:快指针先走n+1步后,慢指针再开始走。
最终慢指针就能指向被删除节点的前一个节点
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy_head = ListNode(self,next=head)
fast = dummy_head
slow = dummy_head
n += 1
while n:
fast = fast.next
n -= 1
while fast != None:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return dummy_head.next
面试题 02.07. 链表相交
题目链接/文章讲解:https://programmercarl.com/面试题02.07.链表相交.html
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
lenA = lenB = 0
cur = headA
while cur:
cur = cur.next
lenA += 1
cur = headB
while cur:
cur = cur.next
lenB += 1
curA,curB = headA,headB
if lenB > lenA:
curA,curB = curB,curA
lenA,lenB=lenB,lenA
gap = lenA-lenB
while gap:
curA = curA.next
gap -= 1
while curA:
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
return None
142.环形链表II
建议:算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0142.环形链表II.html
快指针在环中追上慢指针,那一定是快指针至少在环里已经转了一圈了
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast = head
slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
index1 = head
index2 = fast
while index1 != index2:
index1 = index1.next
index2 = index2.next
return index1
return None
疑问点:为什么为什么第一次在环中相遇,slow的步数是 x + y 而不是 x + 若干环的长度 + y 呢?