关于链表问题,一般情况下要创建一个新的节点,使其next指针指向题目中给定的头节点。目的是方便对头节点进行操作。
我的想法,每次出现待插入节点,都需要从前往后找需要插入的节点位置。
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head==null || head.next==null){
return head;
}
//额外的节点,方便对头头节点进行操作。
ListNode Onlyhead = new ListNode(-1);
Onlyhead.next = head;
//要交换的节点
ListNode cur = head;
while(cur.next!=null){
//如果未发生交换,那么cur指针需要向后移动,如果交换了那么不需要移动。
boolean falg = false;
ListNode temp = cur.next;
for(ListNode pre = Onlyhead;pre.next!=temp;pre = pre.next){
if(pre.next.val>temp.val){
falg = true;
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
break;
}
}
if(!falg){
cur = cur.next;
}
}
return Onlyhead.next;
}
}
结果发现,时间运行比较慢,运行了28ms,为什么,看下面分析。
什么是插入排序,插入排序中已排序好的数组或者链表的最后一个节点一定是最大的节点。
所以我的程序中进行了无效的遍历,只需要提前判断一下就好了。
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head==null || head.next==null){
return head;
}
//额外的节点,方便对头头节点进行操作。
ListNode Onlyhead = new ListNode(-1);
Onlyhead.next = head;
//要交换的节点
ListNode cur = head;
while(cur.next!=null){
//删除掉falg标识符,使其通过前后指针的val的大小方式来判断
ListNode temp = cur.next;
if(cur.val<=temp.val){
cur = cur.next;
continue;
}
for(ListNode pre = Onlyhead;pre.next!=temp;pre = pre.next){
if(pre.next.val>temp.val){
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
break;
}
}
}
return Onlyhead.next;
}
}
结果发现运行了5ms,还是慢,那么请问,为什么需要continue这个关键字。删掉改为if else条件就可以了。
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head==null || head.next==null){
return head;
}
//额外的节点,方便对头头节点进行操作。
ListNode Onlyhead = new ListNode(-1);
Onlyhead.next = head;
//要交换的节点
ListNode cur = head;
while(cur.next!=null){
//删除掉falg标识符,使其通过前后指针的val的大小方式来判断
ListNode temp = cur.next;
if(cur.val<=temp.val){
cur = cur.next;
}else{
for(ListNode pre = Onlyhead;pre.next!=temp;pre = pre.next){
if(pre.next.val>temp.val){
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
break;
}
}
}
}
return Onlyhead.next;
}
}
还是慢,运行了3ms,怎么改,既然一定有一定要发生交换,那么我们就不用for循环
强调,对于链表问题,我们尽量使用while而不是用for循环。
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head==null || head.next==null){
return head;
}
//额外的节点,方便对头头节点进行操作。
ListNode Onlyhead = new ListNode(-1);
Onlyhead.next = head;
//要交换的节点
ListNode cur = head;
while(cur.next!=null){
//删除掉falg标识符,使其通过前后指针的val的大小方式来判断
ListNode temp = cur.next;
if(cur.val<=temp.val){
cur = cur.next;
}else{
ListNode pre = Onlyhead;
while(pre.next.val<temp.val){
pre = pre.next;
}
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
}
}
return Onlyhead.next;
}
}
然后发现还是3ms,时间运行上没变化,但是可读性比较高,已经不错了。