题目
给定一个无序单链表,实现单链表的排序(按升序排序)。
示例1
输入:
[1,3,2,4,5]
返回值:
{1,2,3,4,5}
分析
第一种:直接插入排序,不同与数组的直接插入排序,链表的直接排序从前往后寻找插入位置。
public ListNode sortInList (ListNode head) {
// write code here
if(head == null) {
return null;
}
//返回有序链表头结点
ListNode head1 = new ListNode(-1);
//上一个结点
ListNode lastNode = head1;
//当前节点
ListNode curNode = head1.next;
//
ListNode nextNode = head;
while(nextNode != null) {
curNode = head1.next;
lastNode = head1;
//寻找插入位置,插入位置位于lastNode和curNode之间
while(curNode != null) {
if(nextNode.val < curNode.val) {
break;
}
lastNode = curNode;
curNode = curNode.next;
}
ListNode temp = nextNode.next;
nextNode.next = curNode;
lastNode.next = nextNode;
nextNode = temp;
}
return head1.next;
}
时间复杂度o(n2)
第二种:归并排序,通过双指针找到链表的中间节点,然后将链表分割成两个链表
public ListNode sortInList (ListNode head) {
// write code here
return mergerSort(head);
}
//归并排序
public ListNode mergerSort(ListNode head){
//只有一个节点或者为·空
if(head == null || head.next == null){
return head;
}
//查找链表的中间节点
ListNode slow = head;
ListNode fast = head ;
ListNode left = null, right=null;
/*注意这里的判断条件,对比
while(fast!= null && fast.next!= null){},这种判断条件不能把链表分割成一个单位,最小是两个单位。
*/
while(fast.next != null && fast.next.next!= null){
slow = slow.next;
fast = fast.next.next;
}
//分割成两个链表
ListNode next = slow.next;
slow.next = null;
left = mergerSort(head);
right = mergerSort(next);
return mergeList(left, right);
}
//合并两个有序链表
public ListNode mergeList(ListNode left, ListNode right){
ListNode dummyHead = new ListNode(0);
ListNode cur = dummyHead;
while(left != null && right != null){
if(left.val < right.val){
cur.next = left;
left = left.next;
}
else{
cur.next = right;
right = right.next;
}
cur = cur.next;
}
cur.next = left == null ? right : left;
return dummyHead.next;
}
时间复杂度o(nlogn)