一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情
给你一个链表的头节点
head和一个特定值 **x,请你对链表进行分隔,使得所有 小于x的节点都出现在 大于或等于x的节点之前。
原地操作
第一种思路是: 找到值小于x的节点,移到链表前部分,具体步骤:
- 首先判断链表是不是以小于
x的节点开头的- 如果不是,以哨兵节点为
pre节点, - 如果是的话,找到第一个大于
x节点的前一个节点为pre节点
- 如果不是,以哨兵节点为
- 然后从
pre节点开始,依次判断下一个节点的val与x的关系-
如果大于等于
x,移动指针到下一个位置 -
如果小于
x,移动节点到pre的下一个节点
-
以leetcode示例为例,主要思路可以用下图表示:
function partition(head: ListNode | null, x: number): ListNode | null {
const dummy = new ListNode(-1, head)
let cur = head
let pre = dummy
// 找到值大于等于x节点的前一个节点
while(cur) {
if (cur.val < x) {
pre = cur
cur = cur.next
} else {
break
}
}
// 延用上面的cur
// 遇到比x小的值,就以移动到pre节点后面
while(cur && cur.next) {
if (cur.next.val < x) {
// 移动节点,具体对应的逻辑,可以参照上图理解
let next = cur.next
cur.next = cur.next.next
next.next = pre.next
pre.next = next
pre = next
} else {
cur = cur.next
}
}
return dummy.next
};
- 时间复杂度: O(n)
- 空间复杂度: O(1)
两条链表
还有一种思路也很自然,准备两个链表,一个来存储小于x的值,另一个存储大于等于x的值,然后用前者拼接后者后者
function partition(head: ListNode | null, x: number): ListNode | null {
let lessList = new ListNode(-1)
let greaterList = new ListNode(-1)
// 保存头节点用来拼接
const lessHeaderList = lessList
const greaterHeader = greaterList
let cur = head
while(cur) {
// 收集:小值 连接到小链表中;大值 连接到大链表中
//
if (cur.val < x) {
lessList = lessList.next = cur
} else {
greaterList = greaterList.next = cur
}
cur = cur.next
}
// 将大的部分的尾结点 置null 防止与之前的链表形成cycle
greaterList.next = null
// 小值链表 拼接 大值链表
lessList.next = greaterHeader.next
return lessHeaderList.next
};
- 时间复杂度: O(n)
- 空间复杂度: O(1)