題目連接ide
題目大意:對鏈表進行排序,要求時間複雜度是o(nlgn)。spa
法一:冒泡,不交換結點,而交換結點中的數值。超時了。代碼以下:指針
1 public ListNode sortList(ListNode head) { 2 if(head == null || head.next == null) { 3 return head; 4 } 5 ListNode cur = null, tail = null; 6 cur = head; 7 while(cur.next != tail) { 8 while(cur.next != tail) { 9 //其實這裏交換的是兩個相鄰結點的值,並無交換兩個結點指針 10 if(cur.val > cur.next.val) { 11 int tmp = cur.val; 12 cur.val = cur.next.val; 13 cur.next.val = tmp; 14 } 15 cur = cur.next; 16 } 17 //每一趟排序都會把一個相對最大的數排到最後一個,因此這裏要將tail置爲cur,而不是一直是null 18 tail = cur;//下一次遍歷的尾結點是當前結點 19 //每一趟都再次從頭開始遍歷 20 cur = head;//遍歷起始結點重置爲頭結點 21 } 22 return head; 23 }
法二:歸併,交換結點,利用尾插,誰小誰放在前面。代碼以下(耗時7ms):code
1 public ListNode sortList(ListNode head) { 2 if(head == null || head.next == null) { 3 return head; 4 } 5 //劃分紅兩個鏈表,由快慢指針獲得。 6 //最終slow會指向第二個鏈表的起始位置,fast會指向第二個鏈表的末尾,pre會指向第一個鏈表的末尾 7 ListNode pre = null, slow = head, fast = head; 8 while(fast != null && fast.next != null) { 9 pre = slow; 10 slow = slow.next; 11 fast = fast.next.next; 12 } 13 //第一個鏈表的終結 14 pre.next = null; 15 //分別對兩個鏈表進行排序 16 //head是第一個鏈表的頭,slow是第二個鏈表的頭 17 ListNode l1 = sortList(head); 18 ListNode l2 = sortList(slow); 19 //歸併l1和l2 20 return merge(l1, l2); 21 } 22 private static ListNode merge(ListNode l1, ListNode l2) { 23 //l頭節點初始化爲0,返回的時候返回l.next便可,即不帶頭結點的指針 24 ListNode l = new ListNode(0), p = l; 25 while(l1 != null && l2 != null) { 26 //尾插 27 if(l1.val < l2.val) { 28 p.next = l1; 29 l1 = l1.next; 30 } 31 else { 32 p.next = l2; 33 l2 = l2.next; 34 } 35 p = p.next; 36 } 37 //若是還有結點,則直接放在其後便可 38 if(l1 != null) { 39 p.next = l1; 40 } 41 if(l2 != null) { 42 p.next = l2; 43 } 44 return l.next; 45 }