问题:
解题:
分析:读到要求时间复杂度是n*log(n),那基本上就是快排或者归并排序了,快排需要索引,优先考虑归并进行解答;实际编码 的时候,还是得调试,一不小心就成了无底洞,最重要的就是终止条件,对长度1,2,3,4进行举例调试
class Solution {
public ListNode sortList(ListNode head) {
// 1.先判断特殊条件
if (null == head || null == head.next) {
// 也是终止条件
return head;
}
// 2.标识出中间节点 一定有下一个节点
// 中间节点 若有3个节点,起始middle是第二个元素head+1,doubleAdvance是第三个节点head+2
// 起始先走一步
// 注意,初始化不能先向前移动,以免到时2个分出来的还是2个
ListNode middle = head,
// 快速找到结尾
doubleAdvance = head;
while (null != middle.next && null != doubleAdvance.next && null != doubleAdvance.next.next) {
// 走一步
middle = middle.next;
// 走两步
doubleAdvance = doubleAdvance.next.next;
}
// 3.分成2个链表进行排序
// 左侧直接取头节点
ListNode left = head,
// 右侧获取中间点的下一个节点
right = middle.next;
// 切断两个链表
middle.next = null;
// 4.分别进行排序
ListNode sortLeft = sortList(left),
// 暂时先不多线程
sortRight = sortList(right);
// 5.合
// 左侧的长度>= 当长度是3的时候,左边2个,右边一个,当长度是4时,左边2个,右边是2个
ListNode pointer = new ListNode(0), res = pointer;
while (null != sortLeft && null != sortRight) {
// 小的在前面,先判断小的放到结果中
if (sortLeft.val <= sortRight.val) {
// 左边小弹出左边
pointer.next = sortLeft;
sortLeft = sortLeft.next;
} else {
// 右边小弹出右边
pointer.next = sortRight;
sortRight = sortRight.next;
}
// 指针一直移动
pointer = pointer.next;
}
// 若走到这,说明有一个集合弹空了
// 判断哪个先空了
if (null != sortLeft) {
// 说明右边集合都放进去了
pointer.next = sortLeft;
} else {
pointer.next = sortRight;
}
// 6.返回
return res.next;
}
}
性能:
递归还是比较快的,缺点也很明显,就是占用内存多,以后再优化吧