【LintCode】Sort List(笔记)

Description

Sort a linked list in O(n log n) time using constant space complexity.

Example

Given 1->3->2->null, sort it to 1->2->3->null.

Notes

主要思想就是如何对链表作归并排序。

1.归并排序的思想

2.寻找链表的中间结点(弄两个指针,每次循环p1->next,p2->next->next,p2到达终结点时p1就是中间结点)

3.合并两个已排序链表(合并后的链表注意要有末尾null,为了下一次合并)

Solution

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /*
     * @param head: The head of linked list.
     * @return: You should return the head of the sorted linked list, using constant space complexity.
     */
    ListNode * sortList(ListNode * head) {
        // write your code here
        if(head==NULL || head->next==NULL)
            return head;
        return mergeList(head);
    }
    
    ListNode * mergeList(ListNode *head){
        if(head==NULL || head->next==NULL)  //递归终点注意
            return head;
        ListNode *lh=head;
        ListNode *rh;
        ListNode *p1=head, *p2=head->next;
        while(p2!=NULL && p2->next!=NULL){
            p1 = p1->next;
            p2 = p2->next->next;
        }
        rh = p1->next;
        p1->next = NULL;
        ListNode *lhalf = mergeList(lh);
        ListNode *rhalf = mergeList(rh);
        return merge(lhalf, rhalf);
    }
    
    ListNode * merge(ListNode *lh, ListNode *rh){
        ListNode *sh;
        if(lh->val<=rh->val){  //解决表头问题
            sh = lh;
            lh = lh->next;
        }
        else{
            sh = rh;
            rh = rh->next;
        }
        ListNode *p = sh;      //指针p指向表头
        while(lh&&rh){
            if(lh->val<=rh->val){
                p->next = lh;
                lh = lh->next;
            }
            else{
                p->next = rh;
                rh = rh->next;
            }
            p = p->next;  //链表指针要移动
        }
        if(lh!=NULL)      //merge后要有终点,为了下一次合并
            p->next = lh;
        else
            p->next = rh;
        return sh;
    }
};

这里的merge函数我原先怎么都不能AC的错误写法↓

 

    ListNode * merge(ListNode *lh, ListNode *rh){
        ListNode *sh;
        ListNode *p = sh;     //p这里不能指向sh
        if(lh->val<=rh->val){
            p = lh;
            lh = lh->next;
        }
        else{
            p = rh;
            rh = rh->next;
        }
        while(lh&&rh){
            if(lh->val<=rh->val){
                p->next = lh;
                lh = lh->next;
            }
            else{
                p->next = rh;
                rh = rh->next;
            }
            p = p->next;
        }
        if(lh!=NULL)
            p->next = lh;
        else
            p->next = rh;
        return sh;
    }

如果我一开始让sh申请内存建个链表头,而不是空指针,就不会有这种错了。

 

下面的merge函数是正确的写法↓

 

    ListNode * merge(ListNode *lh, ListNode *rh){
        ListNode *sh = new ListNode(0);
        ListNode *p = sh;        //这样p指向sh就没问题了,而且没有表头问题
        while(lh&&rh){
            if(lh->val<=rh->val){
                p->next = lh;
                lh = lh->next;
            }
            else{
                p->next = rh;
                rh = rh->next;
            }
            p = p->next;
        }
        if(lh!=NULL) 
            p->next = lh;
        else
            p->next = rh;
        p = sh->next;
        sh->next = NULL;
        delete sh;     //把占用内存释放掉
        return p;
    }

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值