leetCode-86-Partition-List
题目描述(中等难度)
题目描述的很难理解,其实回想一下快排就很好理解了。就是快排的分区,将链表分成了两部分,一部分的数字全部小于分区点 x,另一部分全部大于等于分区点 x。最后就是 1 2 2 和 4 3 5 两部分。
解法一
回顾下快排的解法,快排中我们分区用了两个指针,一个指针表示该指针前边的数都小于分区点。另一个指针遍历数组。
1 4 3 2 5 2 x = 3
^ ^
i j
i 表示前边的数都小于分区点 3, j 表示当前遍历正在遍历的点
如果 j 当前指向的数小于分区点,就和 i 指向的点交换位置,i 后移
1 2 3 4 5 2 x = 3
^ ^
i j
然后继续遍历就可以了。
这道题无非是换成了链表,而且题目要求不能改变数字的相对位置。所以我们肯定不能用交换的策略了,更何况链表交换也比较麻烦,其实我们直接用插入就可以了。
同样的,用一个指针记录当前小于分区点的链表的末尾,用另一个指针遍历链表,每次遇到小于分区点的数,就把它插入到记录的链表末尾,并且更新末尾指针。dummy 哨兵节点,减少边界情况的判断。
public ListNode partition(ListNode head, int x) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode tail = null;
head = dummy;
//找到第一个大于等于分区点的节点,tail 指向它的前边
while (head.next != null) {
if (head.next.val >= x) {
tail = head;
head = head.next;
break;
}else {
head = head.next;
}
}
while (head.next != null) {
//如果当前节点小于分区点,就把它插入到 tail 的后边
if (head.next.val < x) {
//拿出要插入的节点
ListNode move = head.next;
//将要插入的结点移除
head.next = move.next;
//将 move 插入到 tail 后边
move.next = tail.next;
tail.next = move;
//更新 tail
tail = move;
}else{
head = head.next;
}
}
return dummy.next;
}
时间复杂度:O(n)。
空间复杂度:O(1)。
解法二
看完两件小事
如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:
- 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
- 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
本文著作权归作者所有,如若转载,请注明出处
转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com