Leetcode ☞ 147. Insertion Sort List ☆

147. Insertion Sort List

My Submissions
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;
}
















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值