给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例:
输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
根据题目可知,最后的链表中所有小于 x 的节点都在大于或等于 x 的节点之前,而且必须保留元素之间的相对关系。例如对于1->4->3->2->5->2来说,分隔的变化过程为: [1] -> [1,4] -> [1,4,3] -> [1,2,4,3] -> [1,2,2,4,3] -> [1,2,2,4,3,5] 。
最终链表可以看作是在保留相关位置关系的基础上的两个链表的链接,其中一个是大于或等于x的元素组成的链表,另一个是小于x的元素组成的链表。因此,一种很自然的想法就是:我们可以新建两个链表beforeHead
和afterHead
分别存放两部分的元素,最后将afterHead
链接到beforeHead
后面即可。
AC code
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
# 双链表法
beforeHead = ListNode(0)
afterHead = ListNode(0)
a, b = afterHead, beforeHead
while head:
if head.val >= x:
a.next = head
a = a.next
else:
b.next = head
b = b.next
head = head.next
a.next = None
b.next = afterHead.next
return beforeHead.next
除了双链表法之外,我们使用额外的单链表同样可以实现。首先新建链表newHead
用于保存大于或等于x
的元素,同时设置指针after
和before
指向新结点,cur
指向给定链表的头结点。从头遍历链表:
-
如果
cur.val >= x
,则将其链接到newHead
右端,同时更新after
和cur
-
如果
cur.val < x
- 如果它是第一个小于
x
的元素,则将其链接到newHead
左端,同时更新cur
和before
,另外为了最后结果的输出,这里设置一个新指针r
指向当前结点 - 否则将其插入到
newHead
前面,同时更新cur
和before
,注意此时r
不改变
- 如果它是第一个小于
-
当链表遍历结束后:
- 如果
r == None
,说明链表中不存在小于x
的元素,返回newHead.next
- 否则执行
before.next = newHead.next
,返回r
- 如果
整个算法流程如下所示:
AC code
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
newHead = ListNode(-1)
before = newHead
after = newHead
cur = head
r = None
while cur:
if cur.val >= x:
after.next= ListNode(cur.val)
after = after.next
else:
node = ListNode(cur.val)
if newHead == before:
node.next = before
before = node
r = before
else:
node.next = newHead
before.next = node
before = before.next
cur = cur.next
if r:
before.next = newHead.next
return r
else:
return newHead.next