LC148 排序链表
0.刷题前需知
这题…虽然算在我们的快速排序专题中
但是这个题不要用快排!因为时间复杂度比题目要求要高!
但是!!
特么面试要考。
啥都得练呗
1.读题
给你链表的头结点 head 请将其按照升序排列 并返回 排序后的链表
2.解题思路
参考题解 排序链表(快排方式)
面试官:你写个链表快排吧(不准交换节点的值哦)
之前还写过一篇快排的小文——三板斧实现快速排序! 可以康康 python实现的 挺清楚的~
先复习下快排思想——
【1】只有一个元素 直接返回这个元素
【2】选定一个pivot基准
【3】小于pivot的分在一边 大于pivot的分在一遍 (这个过程也叫partition分区)
这里注意了!数组的分区是很好做的!左右两个指针不断交换即可!
但是我们这个是链表。。。。。
链表只能单向遍历 所以我们要换一个“partition分区”的方法
浏览了下大佬面字节时候的过程
来看看大佬是怎么想这道题的~
3.代码逻辑
借鉴下大佬的解题思路
【1】选取头节点作为基准值pivot(之前不说是pivot随便儿取不影响时间复杂度嘛~)
【2】遍历链表 比基准值(也就是头节点)小的节点头插在它前面
【2‘】比基准值大的节点尾插在它后面
【3】假设lhead维护的是小于基准值的头插指针
【3’】utail维护的是大于等于基准值的尾插指针
【4】一次对[head , end)快排结束后得到——
【4’】[lhead, head) 这是小于基准值的那一部分
【4‘’】[lhead.next,end) 这是大于基准值的哪部分
【5】分别递归这两部分 最后做一个拼接~
4.Java代码
class Solution {
public ListNode sortList(ListNode head) {
return quicksort(head, null);
}
public static ListNode quicksort(ListNode head, ListNode end){
if(head == end || head.next == end) return head;//【1】设置退出条件
ListNode lhead = head, utail = head, p = head.next;//[3]维护小于基准值的头插指针lhead 大于基准值的尾插指针utail
while (p != end){
ListNode next = p.next;
if (p.val < head.val){//进行头插
p.next = lhead;
lhead = p;
}
else {//进行尾插
utail.next = p;
utail = p;
}
p = next;
}
utail.next = end;
ListNode node = quicksort(lhead, head);
head.next = quicksort(head.next, end);
return node;
}
}
终于是成功了一次!
总之 这个快排单链表的方法还是能不用就不用!太容易失败了!