给按照绝对值排序的链表排序

Submission

运行时间: 156 ms

内存: 45.4 MB

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def sortLinkedList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return head

        pre, cur = head, head.next

        while cur:
            if cur.val < 0:
                pre.next = cur.next
                cur.next = head
                head = cur
                cur = pre.next
            else:
                pre = cur
                cur = cur.next

        return head

Explain

该题解通过链表的遍历,将所有的负数节点移动到链表的前部,达到整体排序的效果。算法从头节点开始遍历,利用两个指针pre和cur,其中pre是cur的前驱节点。在遍历过程中,如果发现当前节点cur的值为负数,则将该节点从链表中断开,并将其插入到链表的最前端,更新head指向新的头节点。然后继续遍历下一个节点。如果cur的值非负,只需移动pre和cur指针继续遍历即可。

时间复杂度: O(n)

空间复杂度: O(1)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def sortLinkedList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return head  # 如果链表为空或只有一个节点,直接返回

        pre, cur = head, head.next  # 初始化前驱节点和当前节点

        while cur:
            if cur.val < 0:  # 当前节点的值为负数
                pre.next = cur.next  # 将当前节点从链表中断开
                cur.next = head  # 将当前节点插入到链表的最前端
                head = cur  # 更新头节点
                cur = pre.next  # 移动当前节点到下一个节点
            else:
                pre = cur  # 移动前驱节点
                cur = cur.next  # 移动当前节点

        return head  # 返回重新排序后的链表头节点

Explore

是的,这种算法中,如果连续存在多个负数节点,其顺序会被倒置。每次遇到负数节点cur,它都会被移动到链表的最前端。因此,较后出现的负数节点会先被移动到前端,导致原始的顺序反转。

在这种情况下,pre的正确性不会受影响。当cur为负数时,即便pre和cur紧邻,更新cur.next指向头节点之后再将pre.next设置为cur.next(此时cur已经移动)仍然可以保持链表的完整性。这是因为cur的移动是先断开与pre的连接,然后再重新连接到链表的前端。

当head节点为负数时,这种初始化不会影响算法的正确执行。因为即便head为负数,算法首次进入循环时不会对head节点进行任何操作;它只是设置了后续遍历的起点。head节点(如果是负数)已经在最前端,因此不需要移动。

这种操作考虑了所有边界情况。即使链表只有一个节点或所有节点都是负数,直接更新head为cur仍然是有效的。如果链表只有一个节点,该节点移动后仍然是head。如果所有节点都是负数,每个节点都将按遇到的顺序依次移到前端,最后一个负数节点将成为新的head。