Total Accepted: 65865
Total Submissions: 228498
Difficulty: Medium
Sort a linked list using insertion sort.
我的AC:(72ms,落后40%,击败36%)(本题为升序排列)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* insertionSortList(struct ListNode* head) {
if(!head || !head->next){ //这个判断不加,就一直是runtime error
return head;
}
struct ListNode *oldHead; //为原链表剩下用于直接插入排序的节点头指针
struct ListNode *i; //临时指针变量:插入节点
struct ListNode *prev,*j; //临时指针变量
oldHead = head->next; //原链表剩下用于直接插入排序的节点链表
head->next = NULL; //目前只含有一个节点的有序链表
while(oldHead){ //遍历剩下无序的链表
//注意:这里for语句就是体现直接插入排序思想的地方
for (i = oldHead, j = head; ((j != NULL) && (j->val < i->val)); prev = j, j = j->next); //无序节点在有序链表中找插入的位置
//退出for循环,就是找到了插入的位置,应该将i节点插入到prev节点之后,j节点之前
//注意:按道理来说,这句话可以放到下面注释了的那个位置也应该对的,但是就是不能。原因:你若理解了上面的第3条,就知道了
//下面的插入就是将i节点即是oldHead节点插入到prev节点之后,已经改变了oldHead节点,所以oldHead节点应该在被修改之前往后移动,不能放到下面注释的位置上去
oldHead = oldHead->next; //无序链表中的节点离开,以便它插入到有序链表中
if (j == head) //插在第一个节点之前
head = i;
else //prev是j的前驱
prev->next = i;
i->next = j; //完成插入动作
//oldHead = oldHead->next;不能放在这里,要放在上面。
}
return head;
}
数组直接插入排序代码:
#include <stdio.h>
//两段都ok,仅仅是for循环时的变量或者前后不一样。总之要想清楚,用草纸画画
void insert_sort(int *arr, int len){
int i, j, tmp;
for (i = 1; i < len; i++){
tmp = arr[i];
j = i - 1;
while (j>=0 && arr[j] > tmp){//注:不知道循环次数时用while更佳,也更清晰。
arr[j + 1] = arr[j--];
//j--;
}
arr[j + 1] = tmp;
}
}
/*void insert_sort(int *array, int n){
int i, j,temp;
for (i = 1; i < n; i++){
if (array[i] < array[i - 1]){
temp = array[i];
for (j = i - 1; j >= 0 && array[j] > temp; j--)
array[j + 1] = array[j];
array[j + 1] = temp;//因为循环完后j--,所以此处要再加回去
}
}
}
*/
跟数组一样的思想。
具体做法是:
1、拎出头结点画在下方成为新链表(有序的,排好的);原链表画在上方,从第二个节点(oldHead)开始遍历。
2、满足条件的,拎出来插入下面的链表中,分两种情况讨论:插在第一个节点之前和其他处。
3、然后下一次遍历。
4、最终返回下方链表的头结点即head。
关键点:
1、oldHead = oldHead->next; 这句的位置,要在上方链表拎出节点插入下方之前!即要使oldHead一直处于上方链表。
2、插入下方链表时,要讨论是否在第一个节点之前。
3、if(!head || !head->next) 这个判断不加,就一直是runtime error
另附一个看来的方法(也是72ms),与我的方法区别有:
1、**p
2、我的方法是判断是否插在新链表的第一个节点之前,此方法是判断是否插在新链表的最后一个节点之后:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* insertionSortList(struct ListNode* head) {
if (!head || !head->next)
return head;
struct ListNode **p, *oldHead, *then;
oldHead = head->next;
head->next = NULL;
while (oldHead) {
p = &head; //p是下方新链表的第一个指针的地址
then = oldHead->next; //因为oldHead会进行操作,为使oldHead = oldHead->next,于此做个记录先。
while (*p && (*p)->val <= oldHead->val) {
p = &(*p)->next;
}
if (*p) {//判断是否插在下方最后一个节点之后
oldHead->next = *p;
*p = oldHead;
} else {
oldHead->next = NULL;
*p = oldHead;
}
oldHead = then;
}
return head;
}