今天继续链表的练习,主要是对于链表的一些操作,结合双指针以及认识一下环形链表。
链表的编辑
题目链接:24. Swap Nodes in Pairs
这一题我在处理的过程中还是遇到了一点困难:
一个是删除的顺序,一定要先画图画出来才能更清楚,也就是:
- dummy_head - Node1 - Node2 - Node3;
- dummy_head 指向 Node2; Node2 指向 Node1;Node1 指向 Node3
在这个过程中 Node1的位置以及最终Node1要指向的Node3都会发生变化,所以我们要设置变量来暂存原始的Node1和Node3。
另一个是:由于是两两交换节点,所以节点每次前进两格,也就是我们要保证当前节点的next与next。next都不为空。
下面是完整的解法:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummyhead = ListNode(next = head)
cur = dummyhead
while cur.next and cur.next.next:
temp = cur.next
temp1 = cur.next.next.next
cur.next = cur.next.next
cur.next.next = temp
cur.next.next.next = temp1
cur = cur.next.next
return dummyhead.next
题目链接:19. Remove Nth Node From End of List
这一题只要把想法转为双指针,让快指针先走n步,那么当快指针到达链表结尾时慢指针自然就停在要删除节点的位置。
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummyhead = ListNode(next = head)
fast = slow = dummyhead
for i in range(n):
fast = fast.next
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return dummyhead.next
链表的相交和环
题目链接:面试题 02.07. Intersection of Two Linked Lists LCCI
这一题题目表述不是很清晰,并不是比较列表某个节点的值值,而是比较列表节点本身。我们采用将列表尾部对齐然后从短列表的头结点处一起开始遍历直到找到第一个相同的点就是相交的节点了。
cur = headA
lenA = 0
while cur:
cur = cur.next
lenA += 1
cur = headB
lenB = 0
while cur:
cur = cur.next
lenB += 1
if lenA > lenB:
cur = headA
dif = lenA - lenB
cur1 = headB
else:
cur = headB
dif = lenB - lenA
cur1 = headA
for i in range(dif):
cur = cur.next
while cur:
if cur == cur1:
return cur
cur = cur.next
cur1 = cur1.next
return None
题目链接:142. Linked List Cycle II
换新列表最难的就是想出判断是否是环形列表的方法和找到交点,这里也是用双指针,用环形列表可以套圈这个特点来进行判断。
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast == slow:
slow = head
while slow != fast:
fast = fast.next
slow = slow.next
return slow
return None