相关题解:
leetcode_效率题解148. Sort List(链表归并排序)
题目链接
【题目】
Sort a linked list using insertion sort.
【分析】
首先复习一下插入排序:
void insert_sort( int a[] , int n ){
int i,j,temp;
for( i = 1; i < n; i ++ ){
temp = a[i];
for( j = i-1 ; j >= 0 ; j -- ){
if( temp < a[j] )
a[j + 1] = a[j];
}
a[j+1] = temp;
}
}
从0到size-1遍历,对于每个位置,对其值与前面已经排序的各个位置进行比较找到应该插入的位置
对于链表的排序就烦人多了
但是思想还是一样的,关键是对于指针的概念要清晰
先来看下面我一开始写的解法:
flag==>遍历所在位置
pre_flag==>flag的前一个结点
temp==>flag前面从前往后遍历的结点
pre==>temp的前一个结点
boo==>布尔值来判断temp到达flag之前是否已经找到合适的插入位置
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if( !head || !head->next ) return head;
ListNode * new_list = new ListNode(0);
new_list->next = head;
ListNode * pre_flag = head;
ListNode * flag = head->next;
bool boo = false;
while(flag != NULL){
ListNode * temp = new_list->next;
ListNode * pre = new_list;
boo = false;
while( temp != flag ){
if( temp->val <= flag->val ){
temp = temp->next;
pre = pre->next;
}
else{
ListNode * temp_node = new ListNode(flag->val);
flag = flag->next;
pre_flag->next = flag;
temp_node->next = temp;
pre->next = temp_node;
boo = true;
break;
}
}
if(!boo){
pre_flag = flag;
flag = flag->next;
}
}
return new_list->next;
}
};
可是跑出来的效率是这样的
再看看上面的解法为什么这么慢,原因是因为有时候遍历到的flag值已经比前一个大,那就没有必要再找插入位置了,直接继续往后flag=flag->next就好了
优化代码:
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if( !head || !head->next ) return head;
ListNode * new_list = new ListNode(0);
new_list->next = head;
ListNode * pre_flag = head;
ListNode * flag = head->next;
while(flag != NULL){
if(pre_flag->val > flag->val){
ListNode * temp = new_list->next;
ListNode * pre = new_list;
boo = false;
while( temp != flag ){
if( temp->val <= flag->val ){
temp = temp->next;
pre = pre->next;
}
else{
ListNode * temp_node = new ListNode(flag->val);
flag = flag->next;
pre_flag->next = flag;
temp_node->next = temp;
pre->next = temp_node;
break;
}
}
}
else{
pre_flag = flag;
flag = flag->next;
}
}
return new_list->next;
}
};
这个效率就是最前面给出的runtime,90%
当然可以写成下面一种简洁点的写法:
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
ListNode * new_list = new ListNode(0);
new_list->next = head;
ListNode * flag = head;
ListNode * pre = new_list;
while(flag){
if( flag->next && flag->next->val < flag->val ){
while( pre->next && pre->next->val < flag->next->val ) pre = pre->next;
/* Insert flag -> next after pre.*/
ListNode * temp = pre->next;
pre->next = flag->next;
flag->next = flag->next->next;
pre->next->next = temp;
/* Move pre back to new_list. */
pre = new_list;
}
else{
flag = flag->next;
}
}
ListNode * ans = new_list->next;
delete new_list;
return ans;
}
};
效率是一样的
再看看python的代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def insertionSortList(self, head):
p = new_list = ListNode(0)
flag = new_list.next = head
while flag and flag.next:
val = flag.next.val
if flag.val < val:
flag = flag.next
continue
if p.next.val > val:
p = new_list
while p.next.val < val:
p = p.next
temp = flag.next
flag.next = temp.next
temp.next = p.next
p.next = temp
return new_list.next