【力扣】148. 排序連結串列
阿新 • • 發佈:2020-11-22
給你連結串列的頭結點head,請將其按 升序 排列並返回 排序後的連結串列 。
進階:
你可以在O(nlogn) 時間複雜度和常數級空間複雜度下,對連結串列進行排序嗎?
示例 1:
輸入:head = [4,2,1,3]
輸出:[1,2,3,4]
示例 2:
輸入:head = [-1,5,3,4,0]
輸出:[-1,0,3,4,5]
示例 3:輸入:head = []
輸出:[]提示:
連結串列中節點的數目在範圍[0, 5 * 104]內
-105<= Node.val <= 105來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/sort-list
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
簡單做法:
public ListNode sortList(ListNode head) { if(head == null || head.next == null){ return head; } List<ListNode> list = new ArrayList<ListNode>(); while(head != null){ list.add(head); head = head.next; } Collections.sort(list,(item1,item2)-> (item1.val - item2.val)); for(int i = 1; i < list.size(); i++){ list.get(i-1).next = list.get(i); } list.get(list.size() -1 ).next = null; return list.get(0); }
//首先先用昨天的題目的排序方式寫一遍、發現時間超限 public ListNode sortList(ListNode head) { if(head == null || head.next == null){ return head; } //我們使用 fast,slow 快慢雙指標法,奇數個節點找到中點,偶數個節點找到中心左邊的節點。 ListNode fast = head.next; ListNode slow = head; while(fast != null && fast.next != null){ fast = fast.next.next; slow = slow.next; } //將連結串列分割,分為左邊和右邊 ListNode temp = slow.next; slow.next = null;//分割需要設定為null ListNode left = sortList(head); ListNode right = sortList(temp); //進行左邊和右邊連結串列的整和 ListNode h = new ListNode(); ListNode result = h; //這個迴圈沒有問題 while(left != null && right != null){ if(left.val < right.val){ h.next = left; left = left.next; }else { h.next = right; right = right.next; } h = h.next; } //這裡有一些疑問: h.next = left || h.next = right 為什麼要這麼設定,這兩種設定效果是一樣的 //因為在迴圈結束時,有可能因為right為空了,或者left為空了,導致沒有給h.next 賦值,所以,再這裡複製。 h.next = right != null ? right : left; return result.next; }
時間複雜度:O(logn)
空間複雜度:O(logn)
以上演算法的整體思想是:找到中心點,將連結串列分割,將分割後的連結串列排序,最後合併.