题目
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
归并
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
return mergeSort(head);
}
public ListNode mergeSort(ListNode head){
if (head == null || head.next == null){
return head;
}
ListNode dummy = new ListNode();
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
while (fast != null && fast.next != null){
fast = fast.next.next;
slow =slow.next;
}
//找到中点
ListNode mid = slow
mid.next = null;
//继续分割,左边分割
ListNode left = mergeSort(dummy.next);
//中点右边分割
ListNode right = mergeSort(mid.next);
//开始合并,第三个链表result用于合并
ListNode result = new ListNode();
ListNode p = result;
while (left != null && right != null){
//left小就放left.val到result
if (left.val < right.val){
p.next = left;
left = left.next;
} else {
p.next = right;
right = right.next;
}
p = p.next;
}
//防止长度不一致时还有剩余元素
if (left == null){
p.next = right;
} else {
p.next = left;
}
return result.next;
}
}
快排
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
return quikSort(head);
}
public ListNode quikSort(ListNode head){
//递归结束条件,只剩1个或者0个
if (head == null || head.next == null){
return head;
}
//找到中点位置,作为分割,用中点值作为基准分割链表为三部分
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
while (fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode mid = slow;
int midVal = mid.val;
//左边部分,即小于中点值
ListNode left = new ListNode();
//中间部分,即等于中点值
ListNode middle = new ListNode();
//右边部分,即大于中点值
ListNode right = new ListNode();
ListNode l = left;
ListNode m = middle;
ListNode r = right;
//分链表
while (head != null){
if (head.val < midVal){
l.next = head;
head = head.next;
l = l.next;
l.next = null;
} else if (head.val > midVal){
r.next = head;
head = head.next;
r = r.next;
r.next = null;
} else {
m.next = head;
head = head.next;
m = m.next;
m.next = null;
}
}
//分好后继续递归分
l = quikSort(left.next);
r = quikSort(right.next);
//分好后中间部分之间连接右边
m.next = r;
//左边为空则直接返回中间头结点
if (l == null){
return middle.next;
} else {
//不为空则左边作为头节点,找到左边末尾直接连接中间节点
ListNode newHead = l;
while (l.next != null){
l = l.next;
}
l.next = middle.next;
return newHead;
}
}
}