题解 | #链表内指定区间反转#
链表内指定区间反转
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
两种解法