牛客-NC70-单链表的排序
NC70. 单链表的排序(easy)
方法一:归并排序(递归)
思路:这道题考察链表排序问题,朴素解法(暴力解)是直接遍历存值再遍历修改值;但更容易打动面试官的可能是归并排序了吧。
我们分两步完成该题,首先是分割,怎么分?需要使用快慢指针去寻找链表的中点,然后以中点为分割点,将链表分为左链表和右链表。再递归进行分割,当head == null || head.next == null
达到递归终止条件。如下图的递归终止图,ps:图片来自于K神。
举个例子:left = 3, right = 2
时,此时,我们需要进行归并排序,也就是图中的merge
操作,合并结束后进行回调,最终我们能够完成整个链表的排序。可以写出以下代码:
import java.util.*;
/* * public class ListNode { * int val; * ListNode next = null; * } */
public class Solution {
/** * * @param head ListNode类 the head node * @return ListNode类 */
public ListNode sortInList (ListNode head) {
// write code here
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode mid = slow.next; // 后半部分
slow.next = null;
ListNode left = sortInList(head); // 左部分
ListNode right = sortInList(mid); // 右部分
ListNode hummyNode = new ListNode(-1);
ListNode cur = hummyNode;
while (left != null && right != null) {
if (left.val >= right.val) {
cur.next = right;
right = right.next;
} else {
cur.next = left;
left = left.next;
}
cur = cur.next;
}
cur.next = left != null ? left : right;
return hummyNode.next;
}
}
时间复杂度: O(nlogn),归并排序时间复杂度。
空间复杂度: O(logn),递归调用函数将带来O(logn)的空间复杂度。
总结:这道题归并方法应该算是最优解,但递归的归并排序并不是最优解,这里分享给大家一个能够达到O(1)的空间复杂度的归并方法,K神。