對鏈表進行插入排序 中等 、排序鏈表 中等
NO.147 對鏈表進行插入排序 中等
思路一:插入排序 思路題目上已經給了,就是動手實現就行了。
- 尋找需要插入排序的節點 next;
- 從 [表頭,next] 區間內尋找到最後一個小於等於 next 的節點 pre;
- 將 next 節點插入到 pre 節點的後面。
public ListNode insertionSortList(ListNode head) {
ListNode dummy = new ListNode(Integer.MIN_VALUE);
dummy.next = head;
ListNode pre = dummy;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
//當發生逆序的時候才需要進行插入排序
if (next != null && next.val < cur.val) {
//pre 尋找 next 節點插入的位置的前驅
while (pre.next != null && pre.next.val <= next.val) {
pre = pre.next;
}
//插入操作,next 插入到 pre節點的後面
cur.next = next.next;
next.next = pre.next;
pre.next = next;
//pre 指針重置
pre = dummy;
} else {
//當前是有序的,不需要插入排序
cur = next;
}
}
return dummy.next;
}
時間複雜度:O(n^2) 插入排序
NO.148 排序鏈表 中等
思路一:歸併排序 O(nlogn)的時間複雜度,要求對鏈表進行歸併排序,而且空間是O(1)。
歸併排序的過程,先快慢指針找到中點,對半拆分鏈表,直至子鏈表剩餘一個節點,再重新合併有序鏈表。
public ListNode sortList(ListNode head) {
//節點爲空,或只有一個節點
if (head == null || head.next == null) return head;
//快慢指針找到中點
ListNode fast = head.next, slow = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
//拆分
ListNode head2 = slow.next;
slow.next = null;
ListNode left = sortList(head);
ListNode right = sortList(head2);
//合併有序鏈表
ListNode dummy = new ListNode(-1);
ListNode p = dummy;
while (left != null && right != null) {
if (left.val <= right.val) {
p.next = left;
left = left.next;
} else {
p.next = right;
right = right.next;
}
p = p.next;
}
p.next = left != null ? left : right;
return dummy.next;
}
時間複雜度:O(nlogn) 空間複雜度:O(logn) 遞歸棧使用的空間。
本人菜鳥,有錯誤請告知,感激不盡!
更多題解和源碼:github