LeetCode.148 排序链表
2021-03-19 00:26
标签:不能 i++ lis linked head 空间 link 复杂度 vat 题目描述:在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。 O(nlogn)的时间复杂度第一时间就是归并排序了,然后要常数级空间,那就不能用递归。 原地归并 LeetCode.148 排序链表 标签:不能 i++ lis linked head 空间 link 复杂度 vat 原文地址:https://www.cnblogs.com/pxy-1999/p/13764235.html
public ListNode sortList(ListNode head) {
//如果只有一个节点直接返回
if (head == null || head.next == null) {
return head;
}
//获取链表长度
int len = ListNodeLength(head);
//定义哨兵节点用于返回
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
//循环时间复杂度O(logn),外层控制轮次,内层进行分割
//i控制分割步长,指数级增长 1,2,4,8...步长超过链表长度就是排序完成
for (int i = 1; i ) {
//设置每一轮分割的起始节点
ListNode pre = dummyNode;
ListNode curNode = dummyNode.next;
//每一轮都从curNode开始,也就是每一轮排序后的头节点,那么终止条件自然就是curNode != null
while(curNode != null){
ListNode leftNode = curNode;
ListNode rightNode = cut(leftNode,i);
//寻找分割的起始节点
curNode = cut(rightNode,i);
//通过pre节点指向排序后的头节点,作为下一轮分割的起始节点
pre.next = mergeTwoLinkedList(leftNode,rightNode);
while (pre.next != null){
pre = pre.next;
}
}
}
return dummyNode.next;
}
/**
* 分割,断链。
* @param head 进行断链操作的节点
* @param step 分割步长,指数级增长,1-2-4-8...
* @return 保存断链节点的下一个节点,作为下一组节点的开始节点
*/
private ListNode cut(ListNode head, int step) {
if (head == null){
return null;
}
//设置分割步长step
for (int i = 1; head.next != null && i ){
head = head.next;
}
ListNode rightNode = head.next;
//断链
head.next = null;
return rightNode;
}
public int ListNodeLength(ListNode head) {
int length = 0;
ListNode cur = head;
while (cur != null) {
cur = cur.next;
length++;
}
return length;
}
public ListNode mergeTwoLinkedList(ListNode l1, ListNode l2) {
ListNode dummyNode = new ListNode(-1);
ListNode cur = dummyNode;
while (l1 != null && l2 != null) {
if (l1.val l2.val) {
cur.next = l1;
l1 = l1.next;
} else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = l1 == null ? l2 : l1;
return dummyNode.next;
}