题目:给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
链接 https://leetcode.cn/problems/partition-list/
temp = right.next
# 将right.next接到right.next的下一个节点
right.next = right.next.next
# temp的下一个节点指向left的下一个节点
# print(right.val,left.val)
temp.next = left.next
left.next = temp
left = left.next
交换结束后即为[ 0, 1, 3, 7, 5, 2, 8, 9],此时left为3,left.next还是7,right还是7。
(2)当right.val >= x时,移动right即可right = right.next
(3)但上面那个双指针当开始时会出现left和right在同一个位置的情况,这时候当right.next.val < x进行交换时会出现问题,
我们来具体分析一下每一步得到的结果:首先设置一个dummy(-1,head)虚拟结点指向head,方便后面返回头结点。这时候,left和right都在dummy(因为我们需要上一个结点才能进行指向,即如果right=dummy.next=head时,如果right.val < x时,由于我们不知道上一个节点,我们根本无法进行有效的移动),但为了有效区分left和right,不让二者指向一个dummy,否则会该链会因为right.next = right.next.next和left = left.next 一次跳两步的原因越来越短
dummy = ListNode(-1,head)
left = dummy
right = ListNode(-1,head)
temp = right.next # 得到temp = 0
# 将right.next接到right.next的下一个节点
right.next = right.next.next # 得到[-1,1, 7, 3, 5, 2, 8, 9]
# temp的下一个节点指向left的下一个节点
temp.next = left.next # 此时left为dummy,因为left和right不是同一个,所以left.next.val=0,对temp及其后面得到[0, 0, 1, 7, 3, 5, 2, 8, 9]
left.next = temp # 此时left和right均为dummy,left.next.val=0,对head及其后面得到[0, 0, 1, 7, 3, 5, 2, 8, 9]
left = left.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
if not head or not head.next:
return head
# 想过双虚拟结点来解决问题
# dummy2 = ListNode(0,head)
# dummy1 = ListNode(0,dummy2)
# left = dummy1
# right = dummy2
dummy = ListNode(-1,head)
left = dummy
right = dummy
while right.next:
if right.next.val < x:
if left == right:
left = left.next
right = right.next
else:
# temp为小于 x 的节点
temp = right.next.val
temp2 = ListNode(temp)
# 将right.next接到right.next的下一个节点
right.next = right.next.next
# temp的下一个节点指向left的下一个节点
# print(right.val,left.val)
temp2.next = left.next
left.next = temp2
left = left.next
else:
right = right.next
# 测试每一步是否移动正确
# print(right.val,left.val)
# la = dummy.next
# ans = []
# while la:
# ans.append(la.val)
# la = la.next
# print(ans)
return dummy.next
class Solution:
def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
if not head or not head.next:
return head
dummy = ListNode(-1,head)
left = dummy
right = dummy
while right.next:
if right.next.val < x:
if left == right:
left = left.next
right = right.next
else:
# temp为小于 x 的节点
temp = right.next
# 将right.next接到right.next的下一个节点
right.next = right.next.next
# temp的下一个节点指向left的下一个节点
temp.next = left.next
left.next = temp
left = left.next
else:
right = right.next
return dummy.next
复杂度分析
时间复杂度: O(n),其中 n 是原链表的长度。我们对该链表进行了一次遍历。
空间复杂度: O(1)
我擦,我好蠢,原来可以将小的放一个链表,大的放另一个链表,然后合起来就行。
class Solution:
def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
if not head or not head.next:
return head
small = ListNode(-1,head)
smallhead = small
large = ListNode(-1,head)
largehead = large
while head:
if head.val < x:
small.next = head
small = small.next
else:
large.next = head
large = large.next
head = head.next
large.next = None
small.next = largehead.next
return smallhead.next
参考:
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/partition-list/solution/fen-ge-lian-biao-by-leetcode-solution-7ade/