刷题Day(4)|代码随想录

61 阅读2分钟

本系列文章是我刷代码随想录过程中的笔记。代码地址:leetcode

今天是我刷“代码随想录”的第四天

今日内容

    1. 两两交换链表中的节点
  • 19.删除链表的倒数第N个节点
  • 面试题 02.07. 链表相交
  • 142.环形链表II

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

这道题使用虚头节点。过程如下

  • 首先定义一个头节点0,此时链表尾0 -> 1 -> 2 -> 3
  • 记录下1,2,3等3个节点的地址
  • 将2的地址赋给0的下一个,同时前进一步,目前在2。此时链表为0 -> 2 -> 3,1
  • 将1的地址赋给2的下一个,同时前进一步,目前在1,此时链表为 0 -> 2 -> 1,3
  • 将3的地址赋给1的下一个,此时链表为 0 -> 2 -> 1 -> 3。可以看到,已经完成了交换。 循环上述步骤即可。注意到,因为有三个节点,因此需要保证 node,node.next,node.next.next均不为空。

下面是求解代码

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]:
        root = ListNode(-1,head)
        node = root
        while node and node.next and node.next.next:
            # 1
            nxt = node.next
            # 2
            nnxt = nxt.next
            # 3
            nnnxt = nnxt.next
            # -> 2
            node.next = nnxt
            node = node.next
            # -> 1
            node.next = nxt
            node = node.next
            # -> 3
            node.next = nnnxt
        return root.next

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

这道题可以采用双指针法。先让快的跳n步,然后快慢同时跳直到快指针为空。此时,慢指针的下一个恰好为要删除的节点。 直接删除就行。

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        head_dummy = ListNode()
        head_dummy.next = head

        slow, fast = head_dummy, head_dummy
        while(n!=0): #fast先往前走n步
            fast = fast.next
            n -= 1
        while(fast.next!=None):
            slow = slow.next
            fast = fast.next
        #fast 走到结尾后,slow的下一个节点为倒数第N个节点
        slow.next = slow.next.next #删除
        return head_dummy.next

或者,也可以先记录链表长度,找到待删除元素的正数序号,然后再进行删除。代码如下

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]:
        num = 0
        tmp = head
        while tmp:
            tmp = tmp.next
            num += 1
        index = num - n
        root = ListNode(-1, head)
        node = root
        for _ in range(index):
            node = node.next
        node.next = node.next.next
        return root.next

leetcode 面试题 02.07. 链表相交

定义a,b两个指针,开始跳。如果a == b,说明啊a是相交点或者a为空。

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None
        a = headA
        b = headB
        while a != b:
            a = a.next if a else headB
            b = b.next if b else headA
        return a

142. 环形链表 II - 力扣(Leetcode)

这道题需要找出环形链表的入口节点。因此在判断有环后,需要从头开始跳,找到入口。

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow, fast = head, head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            # 如果相遇
            if slow == fast:
                p = head
                q = slow
                while p != q:
                    p = p.next
                    q = q.next
                # 你也可以return q
                return p

        return None

总结

链表部分的基础题结束了。有些题还是值得多做几遍的。