題目:在O(n log n)的時間內使用常數級空間複雜度對鏈表進行排序。
思路:由於題目要求,時間複雜度要求爲O(n log n),所以,需要用歸併排序。
- 找到鏈表的中間節點
- 通過中間節點將鏈表1分爲2
- 兩個鏈表進行比較,比較完之後進行合併。
代碼:
package com.company;
import java.util.List;
public class TestNo24 {
//定義單鏈表
static class ListNode{
int val;
ListNode next;
ListNode(int x){
val = x;
next = null;
}
public String toString(){
if(this.next == null){
return String.valueOf(this.val);
}
return this.val + "->" + this.next.toString();
}
}
public static void main(String[] args) {
TestNo24 t = new TestNo24();
ListNode head = new ListNode(4);
head.next = new ListNode(5);
head.next.next= new ListNode(7);
head.next.next.next = new ListNode(9);
head.next.next.next.next = new ListNode(10);
head.next.next.next.next.next = new ListNode(1);
head.next.next.next.next.next.next = new ListNode(2);
// 下面是產生連續的鏈表
// ListNode head = createTestLinkList();
// ListNode newHead = new ListNode(13);
//newHead.next = head;
System.out.println(head);
System.out.println(t.sortList(head));
}
private static ListNode createTestLinkList(){
ListNode head = new ListNode(0);
ListNode curNode = head;
for(int i = 0;i<10;i++){
curNode.next = new ListNode(i);
curNode = curNode.next;
}
return head;
}
public ListNode sortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode mid = getMid(head);
ListNode another ;
if(mid == null){
another = null;
}else{
//此時是兩個鏈表,從鏈表的中間節點分開,中間節點之前之後分別是一個鏈表
another = mid.next;
mid.next = null;
}
return mergeSortedList(sortList(head),sortList(another));
}
//合併兩個有序鏈表爲一個鏈表
private ListNode mergeSortedList(ListNode first,ListNode second){
if(first == null && second == null){
return null;
}
if(first == null){
return second;
}
if(second == null){
return first;
}
//虛擬一個head的前綴節點
ListNode pre = new ListNode(0);
ListNode curNode = pre;
ListNode cur1 = first;
ListNode cur2 = second;
while (cur1 != null && cur2 !=null){
if(cur1.val <= cur2.val){
curNode.next = cur1;
cur1 = cur1.next;
}else{
curNode.next = cur2;
cur2 = cur2.next;
}
curNode = curNode.next;
}
//處理剩下的節點元素
if(cur1 != null){
curNode.next = cur1;
}else{
curNode.next = cur2;
}
return pre.next;
}
//尋找鏈表的中間節點,使用快慢兩個指針
private ListNode getMid(ListNode head){
if(head == null || head.next == null){
return head;
}
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next !=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}