LinkedList专题3
148. Sort List
問題:要求時間度O(NlogN)O(NlogN),空間復雜度是常數,實現數組排序。
思路:之前做過linkedList的插入排序,時間復雜度應該是O(n2)O(n2)。時間復雜度控制在nlogn 一定有二分。二分我只在數組版的list中用過。從頭和尾開始查找,如此之類。這里好像有點難。
學習:把列表分成兩部分;分別排序;再合并。這個又被稱為分治法。確實是這樣。找到一個列表的中間位置,前面的習題練習過了,合并兩個數組也練習過。寫出遞歸版的代碼還是沒有難度的。代碼。因為有棧空間的消耗,所以空間復雜度不是常數,而是logn。
學習2:使用自底向上的策略消除遞歸。這種思路在23 Merge k Sorted Lists 中遇到過。不過我的問題是怎么處理合并后的各個節點。學習別人的代碼吧。
解決方法1:例如鏈表 -1->5->8->4->6。第一步要合并排序 -1,5;8,4;6,null,調用merge函數3次,第一步合并結束后得到的鏈表應該是-1->5->4->8->6。第二步需要合并-1->5,4->8;6,null;調用merge函數2次,第二步合并之后得到鏈表-1->4->5->8。第三步需要合并-1->4->5->8,6;調用merge函數一次,得到-1->4->5->6->8。
這里考慮的代碼細節是:每一步中一個小的合并例如-1,5形成-1->5這樣的列表;5就是下一個合并后列表(4->8)的表頭。
時間復雜度分析:for循環里面split會遍歷n個節點,merge會遍歷n個節點,是O(2n)。for循環會執行logn次。所以時間復雜度O(nlogn)。
解決方法2:當需要合并步長為1的兩個子鏈表的時候,合并后的結果放入隊列中,下次直接從隊列中取子鏈表合并也是可以的??臻g復雜度是O(n)了。
public ListNode sortList(ListNode head) {if (head == null || head.next == null)return head;Queue<ListNode> queue = new LinkedList<ListNode>();ListNode node = head;while (node != null) {ListNode tmp = node.next;node.next = null;queue.add(node);node = tmp;}while(queue.size()>1){queue.add(merge(queue.poll(), queue.poll()));}return queue.poll();}public ListNode merge(ListNode l1, ListNode l2) {if (l1 == null || l2 == null) {return l1 == null ? l2 : l1;}ListNode result = new ListNode(0);ListNode preNode = result;while (l1 != null && l2 != null) {if (l1.val <= l2.val) {preNode.next = l1;l1 = l1.next;} else {preNode.next = l2;l2 = l2.next;}preNode = preNode.next;}if (l1 != null) {preNode.next = l1;}if (l2 != null) {preNode.next = l2;}return result.next;}代碼V1
代碼V2
代碼V3
328 Odd Even Linked List
思路:按照tag刷題,尤其是從easy到hard,你會發現有些難的題目是多個簡單題目的組合。一個一個小問題擊破了,難題就解決了。
代碼
109 Convert Sorted List to Binary Search Tree
思路: 初看題目是沒有思路的。從左到右開始構建樹,想什么情況下該把根節點變為左子樹;左子樹為空的時候不能加右子樹,之類的….腦子里一直在想著數據結構書中講的從非平衡樹到平衡樹的轉換。
學習:整體觀察后發現鏈表的中間節點middle是根;middle的左側是根的左子樹;middle的右側是根的右子樹。
代碼
138. Copy List with Random Pointer
思路:深度科隆要求每個對象都要new,包括每個對象的Object類型的屬性。這里要處理的問題就是死循環。我的思路是迭代。
學習:可以先用一層循環把所有的node new出新的對應節點;再用第二層循環為每個節點賦值next和random屬性。
代碼
817 Linked List Components
思路:遍歷輸入的LinkedList head,如果發現當前節點node.val在G中,而node.next.val不在G中,那結果加1.
代碼
725 Split Linked List in Parts
思路:把一個linkedlist分成k份,每份長度差不超過1。那就是把linkedList均分為k份。對于余數的部分分在前面的子鏈表中。
代碼
2 Add Two Numbers
思路:用兩個列表表示兩個整數,并且是從低位到高位的順序。例如數字是345,鏈表是5->4->3。直接計算兩個列表對應位置的和。如果滿10,就用carry變量保存。再加下一位的時候加上carry。網頁
代碼
445 Add Two Numbers II
思路:把兩個linkedList反轉,用上題的思路做。最后再將結果反轉。
代碼
LinkedList結束。相對來講,LinkedList是比較簡單的。
總結
以上是生活随笔為你收集整理的LinkedList专题3的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下提示命令找不到
- 下一篇: 多位专家解读工业3D打印“叫好不叫座”