题解 | #链表内指定区间反转#

链表内指定区间反转

https://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c

这个是排行榜上的解法,其亮点在于使用了“虚拟头节点”(res)避免了许多空节点和边缘情况,减少了复杂的条件判断。虚拟节点和反转链表时使用的temp节点不是一个东西。

虚拟节点处理的问题包括第一个节点在交换区间的情况。res一开始指向的是head,但在定义pre指针时,pre一开始定义在了res上。则在后面的交换过程中,改变pre的next其实有包括改变res的指向。需要注意的是,这个改变也包括在巧妙的循环控制中,当m=1时,第一个循环是不会执行的。


class Solution:
    def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
        res = ListNode(-1)
        res.next = head
        pre = res
        cur = head
        for i in range(1,m):
            pre = cur
            cur = cur.next
        for i in range(m,n):
            temp = cur.next
            cur.next=temp.next
            temp.next=pre.next
            pre.next=temp
        return res.next


    

自己实现的效率较低的方法,当时间充裕的情况下,这个方法问题不大。效率低是在于将链表当成了数组在操作,先拿出了几个特殊的节点,然后再操作。虽然这个方法时间复杂度仍然是O(n),但倍数太大。同样的,空间复杂度为O(1),但常数项较大。


class Solution:
    def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:

        m = m - 1
        n = n - 1

        def get_k_node(head: ListNode, k: int) -> ListNode:

            if k < 0:
                return None

            if head is None:
                return None

            c = head
            for _ in range(k):
                c = c.next
            return c

        m_pre = get_k_node(head, m-1)
        m_node =  get_k_node(head, m)
        pre = m_node
        cur = get_k_node(head, m+1)
        n_node_next = get_k_node(head, n+1)
        n_node = get_k_node(head, n)

        
        for _ in range(n-m):
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        
        m_pre = get_k_node(head, m-1)
        if m_pre is not None:
            m_pre.next = pre
        m_node.next = n_node_next

        if m == 0:
            return n_node
        else:
            return head

两种解法

全部评论

相关推荐

05-01 22:41
中南大学 Java
点赞 评论 收藏
分享
挣K存W养DOG:我记得好多人说这个公司就是白嫖方案的,现在有大体方案要让你给他展示实现细节了,也是无敌了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务