题目所属分类
原题链接
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
代码案例:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
题解
/**
* 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) {
int n = 0 ;
for(ListNode p = head ; p != null ; p = p.next ) n ++ ;
ListNode dummy = new ListNode(-1);
dummy.next = head ;
for(int i = 1 ; i < n ; i *= 2){//第一行
ListNode cur = dummy;
for(int j = 1 ; j + i <= n ; j += i*2){
ListNode p = cur.next , q = p ;
for(int k = 0 ; k < i ;k++)q=q.next ;
//接下来是归并
int l = 0 , r = 0 ;
while(l < i && r < i && p != null && q !=null){
if(p.val <= q.val){
cur.next = p ;
p = p.next;
l++;
}else{
cur.next = q ;
q = q.next ;
r++ ;
}
cur = cur.next;
}
while(l < i && p != null){
cur = cur.next = p ;
p = p.next;
l++;
}
while( r < i && q != null){
cur = cur.next = q ;
q = q.next ;
r++ ;
}
cur.next = q ;//更新每一个cur
}
}
return dummy.next;
}
}
通过快慢指针的方式找到当前链表的中点,将左边部分和右边部分分开形成两个链表,并分别进行排序,注意的是左边部分的尾指针需要指向 null,最后排序后的两个链表进行合并,并进行返回
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
static ListNode merge(ListNode left, ListNode right)
{
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while(left != null && right != null)
{
if(left.val <= right.val)
{
cur.next = left;
left = left.next;
}
else
{
cur.next = right;
right = right.next;
}
cur = cur.next;
}
if(left != null) cur.next = left;
else cur.next = right;
return dummy.next;
}
public ListNode sortList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode slow = head, fast = head.next;
while(fast != null && fast.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
fast = slow.next;
slow.next = null;
ListNode left = sortList(head);
ListNode right = sortList(fast);
return merge(left, right);
}
}