思路:
数组的插入排序是从最后一个从后往前遍历找到合适的位置插入,而链表不能往前遍历,则需要一个带头节点的指针,从前往后遍历找到合适的位置插入
代码:
class Solution {
public ListNode insertionSortList(ListNode head) {
//是return head而不是0
if(head==null) return head;
//只是一个空链表,不带头节点
ListNode hair=new ListNode(0);
hair.next=head;
ListNode lastSorted=head,curr=head.next;
//此处是curr而不是curr.next
while(curr!=null){
//是"<="
if(lastSorted.val<=curr.val){
lastSorted=lastSorted.next;
curr=curr.next;
}else{
//用到的时候再创建,不要一开始就创建。这样可以减少内存开销
ListNode prev=hair;
//是"<="
while(prev.next.val<=curr.val){
prev=prev.next;
}
lastSorted.next=curr.next;
curr.next=prev.next;
prev.next=curr;
//重置,把curr继续放在lastSorted后面,继续遍历
curr=lastSorted.next;
}
}
return hair.next;
}
}
分解:
1)需要一个带头节点的指针hair,一个lastsorted和curr。lastsorted相当于已经排好序的最后一个元素,属于内循环。curr是没有排好序的第一个元素,属于外循环。一个prev,用于从前往后内循环,在内循环最后一个元素比外循环第一个元素大的时候才创建,这样可以减少内存的消耗,提高性能
2)若内循环最后一个元素比外循环第一个元素小,则两个指针都向后移一个
if(lastSorted.val<=curr.val){
lastSorted=lastSorted.next;
curr=curr.next;
}
3)调换顺序的代码
ListNode prev=hair;
//是"<="
while(prev.next.val<=curr.val){
prev=prev.next;
}
lastSorted.next=curr.next;
curr.next=prev.next;
prev.next=curr;
//重置,把curr继续放在lastSorted后面,继续遍历
curr=lastSorted.next;