代码随想录算法训练营day04| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、160.链表相交、142.环形链表II

24. 两两交换链表中的节点

题目理解

  • 不能修改结点内部的值,那么就是链表的指针改变
  • 直接模拟过程,加上哑结点方便操作
  • 因为交换比较复杂,可以多使用几个临时结点使过程更清晰
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummy_head = ListNode(0, head)
        cur = dummy_head
        while cur.next and cur.next.next:
            temp = cur.next.next.next
            first_node = cur.next
            second_node = cur.next.next
            first_node.next = temp
            second_node.next = first_node
            cur.next = second_node
            cur = cur.next.next
        return dummy_head.next

19.删除链表的倒数第N个节点

两种方法

  • 遍历第一次,得到长度;遍历第二次,找到要删除的元素
  • 双指针法,慢指针指向哑结点,快指针先走n步
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummy_head = ListNode(0, head)
        slow = dummy_head
        fast = dummy_head
        for _ in range(n):
            fast = fast.next
            if fast is None:
                return head
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return dummy_head.next

看完题解之后,发现可以先走n+1步,和我写的意思差不多,我写的循环条件是fast.next,相当于在n的基础上又走了一步

160.链表相交

数值相同并不代表链表相交

思路:获取两条链表的长度,长的链表先走几步和短的链表一样,然后一起走,查看是否相等

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
        cur = headA
        lenA = 0
        lenB = 0
        while cur:
            lenA += 1
            cur = cur.next

        cur = headB
        while cur:
            lenB += 1
            cur = cur.next

        if lenA >= lenB:
            fast = headA
            slow = headB
            gap = lenA - lenB
        else:
            fast = headB
            slow = headA
            gap = lenB - lenA

        for _ in range(gap):
            fast = fast.next

        while fast:
            if fast == slow:
               return fast
            fast = fast.next
            slow = slow.next

        return

142.环形链表II

两种方法

思路1:使用哈希表存储,如果遇到了表中已经有的,则是入环的第一个节点,空间复杂度为O(n)

思路2:快慢指针

  1. 先判断是否有环 (快慢指针一定会在环中相遇)
  2. 再找到入环的第一个节点 (可以使用公式找规律,在相遇后,头指针和当前指针同时开始一步步移动,相遇点为环入口)

下面快慢指针的代码不够简洁,可以直接在快慢指针相遇的时候去判断环的入口在哪里

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:  # 快慢指针相遇了
                break

        # 判断是哪种情况跳出了循环,如果是遇见空指针的话,那么肯定不存在环,直接返回。否则进行第二步,寻找环
        if fast is None or fast.next is None:
            return None

        slow = head
        while slow != fast:
            slow = slow.next
            fast = fast.next

        return slow

总结

链表总结要点:当有删除或者增加元素的时候,虚拟头结点能够简化操作

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值