Sort a linked list using insertion sort.
----------------------------------------------------------------------------------------------------------------------------------------
插入排序是假设前面一部分已经是有序的,后面元素a 不满足有序,则寻找前面有序序列的合适的位置,插入a。
插入排序默认第一个是有序状态。
假设我们有3 -> 5 -> 4 ->1 -> 2这样一个链表。
一开始,3有序
接下来,cur = 5 : 5 > 3,有序
接着,cur = 4 : 4 < 5, 无序,需要进行插入操作。
我们从头开始找合适的插入位置:
3 < 4不适合,
5 > 4,适合。
选择在3, 5中插入。
明白了这样一个流程后,我们来看看代码的实现。
我们先造一个fakeNode, fakeNode.next = head。这样是为了在头结点位置插入方便。
1.
2个指针,一个cur:当前遍历到的结点,一个pre: 当前结点的前一个结点。
此时 cur > pre的时候,说明是一个有序状态。
cur = cur.next ; pre = pre.next,继续遍历。
2.
当cur 指向4的时候,无序了,需要插入。
3.
我们先需要寻找一个合适的插入位置。
我们让searchPre指针从fakeNode出发,searchCur指针从head出发。
当searchCur.val < cur.val的时候,继续往后遍历。
4.
此时,searchCur.val > cur.val了,插入点找到了!
需要在searchPre和searchCur间插入 cur
5. 具体的更新步骤
5.1为了让cur消除掉。pre.next = pre.next.next
5.2 让searchPre.next 指向 cur
5.3 temp指针指向cur.next , 让cur.next指向searchCur。cur插入到searchPre和searchCur中了。
5.4. 最后,cur = temp, 更新cur这一步骤非常重要!
我们知道插入排序的时间复杂度为 O ( n ^ 2 ), 空间为 O ( 1 )
运行时间:
代码:
public ListNode insertionSortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode fakeNode = new ListNode(-1);
fakeNode.next = head;
ListNode pre = head, cur = pre.next;
while (cur != null) {
if (cur.val >= pre.val) {
cur = cur.next;
pre = pre.next;
}
else {
ListNode searchPre = fakeNode;
ListNode searchCur = searchPre.next;
while (searchCur.val < cur.val) {
searchPre = searchPre.next;
searchCur = searchCur.next;
}
pre.next = pre.next.next;
searchPre.next = cur;
ListNode temp = cur.next;
cur.next = searchCur;
cur = temp;// update cur to the next element.
}
}
return fakeNode.next;
}