代码随想录算法训练营第四天 | 24:两两交换节点 ,19:删除倒数第N个节点,面试02.07:链表相交 142:环形链表

77 阅读2分钟

今天继续链表的练习,主要是对于链表的一些操作,结合双指针以及认识一下环形链表。

链表的编辑

题目链接: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