zoukankan      html  css  js  c++  java
  • 合并两个有序链表

    将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

    示例:

    输入:1->2->4, 1->3->4
    输出:1->1->2->3->4->4

     

    思路1:利用stack模板

    代码:

    #include <iostream>
    #include <stack>
    using namespace std;
    
    int main(){
        int a,b;
        int i= 0;
        stack<int>st1,st2,st3;
        while( scanf("%d->",&a)){
            st1.push(a);
        }
        getchar();
        while( scanf("%d->",&a)){
            st2.push(a);
        }
        while(!st1.empty()&&!st2.empty())
        {
            a = st1.top();
            b = st2.top();
            if(a<b){
                st3.push(b);
                st2.pop();
    
            }else if (a==b)
            {
                st3.push(b);
                st1.pop();
                st2.pop();
            }else{
                st3.push(a);
                st1.pop();
            }
        }
    
        if (!st1.empty())
        {
            st3.push(st1.top());
            st1.pop();
        }
        if (!st2.empty())
        {
            st3.push(st2.top());
            st2.pop();
        }
        while (!st3.empty())
        {
            cout<<st3.top()<<"->";
            st3.pop();
        }
        cout<<"null"<<endl;
    }

    结果:

    1->2->4,1->3->4
    1->2->3->4->null

     

     

    思路2:采用数据结构的链表,定义一个指向头节点的Lc,和一个指向尾部节点的pc,属于常规的暴力破解。

    #include<malloc.h>
    #include<iostream>
    using namespace std;
    #define OVERFLOW -2
    typedef struct Node{
        int data;
        struct Node *next;       
    }Node,*LinkList;
    
    int InitList(LinkList &L){ 
        L = (LinkList)malloc(sizeof(Node));
        if(!L)
            exit(OVERFLOW);
        L->next = NULL;
        return 1;
    }
    void CreatList(LinkList &L, int n){
        LinkList p,r;
        r = L;
        int a;
        for(int i = 0; i < n; i++){
            p = (LinkList)malloc(sizeof(Node));
            scanf("%d",&a);
            p->data = a;
            r->next = p;
            r = p;
        }
        r->next = NULL;
    }
    
    void PrintList(LinkList &L){//输出单链表 
        LinkList q;
        q = L->next;
        while(q){ 
            printf("%d ",q->data);
            q = q->next;
        }  
    }
    
    void Combine(LinkList La, LinkList Lb, LinkList Lc){
        LinkList pa,pb,pc;
        pa = La->next;
        pb = Lb->next;
        Lc = pc = La;
        while(pa && pb){
            if(pa->data <= pb->data){
                pc->next = pa;
                pc = pa;
                pa = pa->next;
            }
            else{
                pc->next = pb;
                pc = pb;
                pb = pb->next;
            }
        }
        pc->next = pa? pa:pb;
        free(Lb);
        PrintList(Lc);
    }
    
    int main(){
           int m,n;
        LinkList LA,LB;
        InitList(LA);
        InitList(LB);
        cout<<"Enter the number of La"<<endl;
        cin>>m;
        CreatList(LA,m);
        cout<<"Enter the number of Lb"<<endl;
        cin>>n;
        CreatList(LB,n);
        cout<<endl; 
        cout<<"the number is La"<<endl;
        cout<<"-----------------------"<<endl;
        PrintList(LA);
        cout<<endl; 
        cout<<"the number is Lb"<<endl;
        cout<<"-----------------------"<<endl;
        PrintList(LB);
        cout<<"merge La and Lb"<<endl;
        LinkList Lc;
        InitList(Lc);
        Combine(LA,LB,Lc); 
        return 0; 
    }

    思路3:暴力破解的递归版

     

     

       也就是说,两个链表头部值较小的一个节点与剩下元素的 merge 操作结果合并。

    算法

      我们直接将以上递归过程建模,同时需要考虑边界情况。

      如果 l1 或者 l2 一开始就是空链表 ,那么没有任何操作需要合并,所以我们只需要返回非空链表。否则,我们要判断 l1 和 l2 哪一个链表的头节点的值更小,然后递归地决定下一个添加到结果里的节点。如果两个链表有一个为空,递归结束。

     

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if (l1 == nullptr) {
                return l2;
            } else if (l2 == nullptr) {
                return l1;
            } else if (l1->val < l2->val) {
                l1->next = mergeTwoLists(l1->next, l2);
                return l1;
            } else {
                l2->next = mergeTwoLists(l1, l2->next);
                return l2;
            }
    }

    复杂度分析

      时间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度。因为每次调用递归都会去掉 l1 或者 l2 的头节点(直到至少有一个链表为空),函数 mergeTwoList 至多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,即 O(n+m)。

    空间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度。递归调用 mergeTwoLists 函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 mergeTwoLists 函数最多调用 n+m次,因此空间复杂度为 O(n+m)。

     

    思路4:迭代
    思路

      我们可以用迭代的方法来实现上述算法。当 l1 和 l2 都不是空链表时,判断 l1 和 l2 哪一个链表的头节点的值更小,将较小值的节点添加到结果里,当一个节点被添加到结果里之后,将对应链表中的节点向后移一位。

    算法

      首先,我们设定一个哨兵节点 prehead ,这可以在最后让我们比较容易地返回合并后的链表。我们维护一个 prev 指针,我们需要做的是调整它的 next 指针。然后,我们重复以下过程,直到 l1 或者 l2 指向了 null :如果 l1 当前节点的值小于等于 l2 ,我们就把 l1 当前的节点接在 prev 节点的后面同时将 l1 指针往后移一位。否则,我们对 l2 做同样的操作。不管我们将哪一个元素接在了后面,我们都需要把 prev 向后移一位。

      在循环终止的时候, l1 和 l2 至多有一个是非空的。由于输入的两个链表都是有序的,所以不管哪个链表是非空的,它包含的所有元素都比前面已经合并链表中的所有元素都要大。这意味着我们只需要简单地将非空链表接在合并链表的后面,并返回合并链表即可。

     

     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            ListNode* preHead = new ListNode(-1);
    
            ListNode* prev = preHead;
            while (l1 != nullptr && l2 != nullptr) {
                if (l1->val < l2->val) {
                    prev->next = l1;
                    l1 = l1->next;
                } else {
                    prev->next = l2;
                    l2 = l2->next;
                }
                prev = prev->next;
            }
    
            // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
            prev->next = l1 == nullptr ? l2 : l1;
    
            return preHead->next;
        }

     

    因上求缘,果上努力~~~~ 作者:每天卷学习,转载请注明原文链接:https://www.cnblogs.com/BlairGrowing/p/12814803.html

  • 相关阅读:
    mac 系统下删除目录的所有.svn文件
    java DES加密解密文件
    也许,未来需要重新规划
    android选择图片或拍照图片上传到服务器(包括上传参数)
    iOS DES ECB模式对称加密解密
    iOS开发中防止键盘挡住UITextField解决方案
    xCode 4.X 免证书真机公布及调试
    iOS 获取手机的型号,系统版本,软件名称,软件版本
    java DES ECB模式对称加密解密
    解决error: failed to launch"/private/var/mobile/Applications/XX" timed out waiting for app to launch
  • 原文地址:https://www.cnblogs.com/BlairGrowing/p/12814803.html
Copyright © 2011-2022 走看看