LeetCode.148 排序链表
Posted 硬盘红了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode.148 排序链表相关的知识,希望对你有一定的参考价值。
题目描述:在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
O(nlogn)的时间复杂度第一时间就是归并排序了,然后要常数级空间,那就不能用递归。
原地归并
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 < len; i = i <<1) { //设置每一轮分割的起始节点 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 < step; 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; }
以上是关于LeetCode.148 排序链表的主要内容,如果未能解决你的问题,请参考以下文章