排序链表题目:
在给定的链表的头节点head,将其按升序排列并返回排序后的链表。
备注:在O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序
题目分析:
- 首先得到链表的长度
- 定义归并排序中的步长并且每次循环结束step*2
- 第一步时由于链表的头节点会发生改变 特殊处理
- 将排序好的组进行连接
public ListNode sortList(ListNode head) {
// 获取点的总数
int n = 0;
ListNode cur = head;
while (cur != null) {
n++;
cur = cur.next;
}
ListNode l1, r1, l2, r2, next, lastTeamEnd;
for (int step = 1; step < n; step <<= 1) {
// 第一步特殊情况 单独处理
l1 = head;
r1 = findEnd(l1, step);
l2 = r1.next;
r2 = findEnd(l2, step);
next = r2.next;
r1.next = null;
r2.next = null;
merge(l1, r1, l2, r2);
head = start;
lastTeamEnd = end;
while (next != null) {
l1 = next;
r1 = findEnd(l1, step);
l2 = r1.next;
if (l2 == null) {
lastTeamEnd.next = l1;
break;
}
r2 = findEnd(l2, step);
next = r2.next;
r1.next = null;
r2.next = null;
merge(l1, r1, l2, r2);
lastTeamEnd.next = start;
lastTeamEnd = end;
}
}
return head;
}
// 寻找最后值的指针
public static ListNode findEnd(ListNode head, int k) {
while ( head.next != null&&--k != 0 ) {
head = head.next;
}
return head;
}
public static ListNode start;
public static ListNode end;
// merge过程
public static void merge(ListNode l1,ListNode r1,ListNode l2,ListNode r2){
ListNode pre;
// 那边小从那边开始 并且把指针指向这一组的下一个指针
if (l1.val <= l2.val){
start = l1;
pre = l1;
l1 = l1.next;
}else {
start = l2;
pre = l2;
l2 = l2.next;
}
// 将2个组的连接在一起
while (l1 !=null && l2 !=null){
if (l1.val <= l2.val){
pre.next = l1;
pre = l1;
l1 = l1.next;
}else {
pre.next = l2;
pre = l2;
l2 = l2.next;
}
}
// 将最后的值放入全局变量中
if (l1!=null){
pre.next = l1;
end = r1;
}else {
pre.next = l2;
end = r2;
}
}