Given the head of a singly linked list, sort the list using insertion sort, and return the sorted list’s head.
The steps of the insertion sort algorithm:
Insertion sort iterates, consuming one input element each repetition and growing a sorted output list.
At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list and inserts it there.
It repeats until no input elements remain.
The following is a graphical example of the insertion sort algorithm. The partially sorted list (black) initially contains only the first element in the list. One element (red) is removed from the input data and inserted in-place into the sorted list with each iteration.
Constraints:
The number of nodes in the list is in the range [1, 5000].
-5000 <= Node.val <= 5000
本题是链表的插入排序,遍历单向链表的每个node,删除该node,插入到正确的位置,使整个链表的节点从小到大排列。
思路:
比较纠结的就是指针问题,用几个指针,怎么移动。
因为是单向链表,如果删除node的话,需要知道当前node的前一个节点preNode, 通过修改preNode.next来删除当前node
还需要维护一段已经排好序的链表,分解线就是当前node,它的前半段是已经排好序的,后半段是待删除和插入的部分
这两段都需要两个指针,一个指向前面节点的preNode, 一个指向当前节点的curNode
head节点是会变的,因为如果在head前插入node,head就需要重新指向最前面的node
为了不频繁变动head,我们重新声明一个newHead,最开始用newHead.next指向head,
那么后续只需要变动newHead.next即可,最后返回newHead.next
前半段我们可以不用两个指针,只用一个指针代替preNode和curNode, 怎么做到呢,这就是newHead的好处,
我们声明一个tmp,指向newHead,用tmp.next表示curNode, tmp本身表示preNode
另外,在遍历后半段preNode和curNode时,如果preNode <= curNode时可以直接跳过的,因为已经排好序了
preNode > curNode时,删掉curNode, 遍历前半段,那肯定想问了,遍历的终止条件是什么呢?
这时注意到这个遍历的前提是preNode > curNode, 那么肯定会有node的值>curNode, 一定会停下来插入值,插值结束后就跳出了
不要忘了删除完curNode后,把curNode移动到preNode.next的位置
//2ms
public ListNode insertionSortList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode newHead = new ListNode();
newHead.next = head;
ListNode tmpNode = newHead;
ListNode preNode = head;
ListNode curNode = head.next;
while(curNode != null) {
if(preNode.val <= curNode.val) {
preNode = preNode.next;
curNode = curNode.next;
} else {
tmpNode = newHead;
while(tmpNode.next.val <= curNode.val) {
tmpNode = tmpNode.next;
}
preNode.next = curNode.next;
curNode.next = tmpNode.next;
tmpNode.next = curNode;
curNode = preNode.next;
}
}
return newHead.next;
}