leetcode 链表排序

对链表排序,用归并排序。题目要求空间时间复杂度为O(nlogn),但是空间复杂度为O(1)

1.自己写的程序,时间复杂度为O(nlogn),但是空间复杂度为O(n)

用快慢指针(分别走2步和1步)找到中间节点。但是最后排序的部分,用复制将排好序的部分粘贴会原来链表中,这个方法比较笨,而且增加空间复杂度,并不满足题目要求

leetcode 提交的时候说runtime error,但自己执行是通过的,可能因为时间复杂度的原因吧,需要后期再改

void mergesort(ListNode* head, ListNode* as, ListNode* ae, ListNode* bs, ListNode* be){
    vector<int> vec;
    ListNode* ps = as;
    ListNode* pe = be;
    int i= 0;
    int anum = ae - as;
    int bnum = be - bs;
    int ia = 0, ib = 0;
    while(ia <= anum && ib <= bnum){
        if(as->val <= bs->val){
            vec.push_back(as->val);
            as = as->next;
            ia++;
        }
        else{
            vec.push_back(bs->val);
            bs = bs->next;
            ib++;
        }
    }
    while(ia <= anum){
        vec.push_back(as->val);
        as = as->next;
        ia++;
    }
    while(ib <= bnum){
        vec.push_back(bs->val);
        bs = bs->next;
        ib++;
    }
    int pnum = pe - ps;
    int ip = 0;
    while(ip <= pnum){
        ps->val = vec[i++];
        ps = ps->next;
        ip++;
    }
}

void merge(ListNode* head,ListNode* start, ListNode* end){
    if(start < end){
        ListNode* former=start, * latter = start;
        int snum = end - start;
        int latt = 0;
        while(latt + 2 <= snum){
            former = former->next;
            latter = latter->next->next;
            latt = latt + 2;
        }
        if(latt+1 == snum){
            latter = latter->next;
        }
        merge(head,start,former);
        merge(head,former->next,latter);
        mergesort(head,start,former,former->next,end);
    }
    else
        return;
}


2.leetcode中大神的代码,这里粘贴是为了自己以后找起来方便

它是自底向上的,归并起来。step为1,2,4,8....

/**
 * merge the two sorted linked list l1 and l2,
 * then append the merged sorted linked list to the node head
 * return the tail of the merged sorted linked list
 */


ListNode* merge(ListNode* l1, ListNode* l2, ListNode* head){
    ListNode *cur = head;
    while(l1 && l2){
        if(l1->val > l2->val){
            cur->next = l2;
            cur = l2;
            l2 = l2->next;
        }
        else{
            cur->next = l1;
            cur = l1;
            l1 = l1->next;
        }
    }
    cur->next = (l1 ? l1 : l2);
    while(cur->next) cur = cur->next;
    return cur;
}

/**
 * Divide the linked list into two lists,
 * while the first list contains first n ndoes
 * return the second list's head
 */

ListNode* split(ListNode *head, int n){
    //if(!head) return NULL;
    for(int i = 1; head && i < n; i++) head = head->next;
    
    if(!head) return NULL;
    ListNode *second = head->next;
    head->next = NULL;
    return second;
}

ListNode *sortList(ListNode *head) {
    if(!head || !(head->next)) return head;
    
    //get the linked list's length
    ListNode* cur = head;
    int length = 0;
    while(cur){
        length++;
        cur = cur->next;
    }
    
    ListNode dummy(0);
    dummy.next = head;
    ListNode *left, *right, *tail;
    for(int step = 1; step < length; step <<= 1){
        cur = dummy.next;
        tail = &dummy;
        while(cur){
            left = cur;
            right = split(left, step);
            cur = split(right,step);
            tail = merge(left, right, tail);
        }
    }
    return dummy.next;
}



其余补充的部分,对链接初始化和输出打印部分

/**
 * Definition for singly-linked list.*/
  struct ListNode {
      int val;
      ListNode *next;
      ListNode(int x) : val(x), next(NULL) {}
  };
 
ListNode* init(int a[], int n){
    ListNode* q = NULL, *head = NULL;
    for(int i = 0; i < n; i++){
        ListNode* p = new ListNode(0);
        p->val = a[i];
        if(i==0){//不要忽略头结点的赋值
            head = q = p;
            continue;
        }
        q->next=p;
        q = q->next;
    }
    q->next = NULL;
    return  head;
    
}



void prints(ListNode* head){
    while(head){
        cout<<head->val<<" ";
        head = head->next;
    }
}


    


int main(int argc, const char * argv[]) {
    int a[]={2,5,3,7,9,4,1,8};
    //int a[]={2,1};
    ListNode* head =new ListNode(0);
    head=init(a,8);
    ListNode* L = sortList(head);
    prints(L);
    return 0;
}


3.最后提交上去的版本,能运行通过且过程简单易懂,也是从别人那里看到的

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:

    void mergesort(ListNode* head, ListNode* as, ListNode* ae, ListNode* bs, ListNode* be){
    vector<int> vec;
    ListNode* ps = as;
    ListNode* pe = be;
    int i= 0;
    int anum = ae - as;
    int bnum = be - bs;
    int ia = 0, ib = 0;
    while(ia <= anum && ib <= bnum){
        if(as->val <= bs->val){
            vec.push_back(as->val);
            as = as->next;
            ia++;
        }
        else{
            vec.push_back(bs->val);
            bs = bs->next;
            ib++;
        }
    }
    while(ia <= anum){
        vec.push_back(as->val);
        as = as->next;
        ia++;
    }
    while(ib <= bnum){
        vec.push_back(bs->val);
        bs = bs->next;
        ib++;
    }
    int pnum = pe - ps;
    int ip = 0;
    while(ip <= pnum){
        ps->val = vec[i++];
        ps = ps->next;
        ip++;
    }
}

void merge(ListNode* head,ListNode* start, ListNode* end){
    int hnum = end - start;
    if(hnum > 0){
        ListNode* former=start, * latter = start->next;
        while(latter!= NULL && latter->next != NULL){
            former = former->next;
            if(latter->next->next == NULL)
                latter = latter->next;
                else
                latter = latter->next->next;
        }
        
        merge(head,start,former);
        merge(head,former->next,latter);
        mergesort(head,start,former,former->next,end);
    }
    else
        return;
}

    ListNode* sortList(ListNode* head) {
        if(head == NULL || head->next == NULL)
            return head;
        ListNode* p = head;
        while(p->next != NULL)
            p = p->next;
        merge(head,head,p);
        return head;
        }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值