【数据结构1800题 (陈守孔) 第2章】线性表 算法设计题全解

【2.5】

【题目大意】去掉链表中绝对值重复过的数字(只保留第一个)

【解法】删除的时候用当前枚举到的节点的前一个节点,这样的话能够方便删除。用数组来判重。

【代码】

int flag[10000+10];
void quchong(LNode *L){
    LNode *p = L;
    while (p->next!=NULL){
        int t = p->next->data;
        if (t<0) t = -t;
        if (flag[t]==0){
            flag[t] = 1;
            p = p->next;
        }else{
            LNode *temp = p->next;
            p->next = temp->next;
            free(temp);
        }
    }
}

  

【2.6】

【题目大意】让你把两个有序链表合并成一个有序链表

【做法】就按照归并排序的思路合并就ojbk了,合并的时候把合并后的结果接在第一个链表的头结点后面就好!

【代码】

//合并之后,放到第一个链表里面
void _merge(LNode *h1,LNode *h2){
    LNode *p1 = h1->next;LNode *p2 = h2->next,*t;
    h1->next = NULL;
    t = h1;
    while (p1!=NULL && p2!=NULL){
        if (p1->data<p2->data){
            t->next = p1;
            t = p1;
            p1 = p1->next;
        }else{
            t->next = p2;
            t = p2;
            p2 = p2->next;
        }
    }
    while (p1!=NULL) {
        t->next = p1;t = p1;
        p1=p1->next;
    }

    while (p2!=NULL){
        t->next = p2;t = p2;
        p2 = p2->next;
    }
}

  

【2.7】

【题目大意】一个升序一个逆序的链表,让你合并成一个有序的单链表。

【做法】把逆序的那个原地倒置就好

//先把第二个链表原地倒置 然后当成2.6的合并做就好
void _merge(LNode *h1,LNode *h2){
    LNode *p = h2->next;
    h2->next = NULL;
    while (p){
        LNode * temp = p->next;
        p->next = h2->next;
        h2->next = p;
        p = temp;
    }

    LNode *p1 = h1->next;LNode *p2 = h2->next,*t;
    h1->next = NULL;
    t = h1;
    while (p1!=NULL && p2!=NULL){
        if (p1->data<p2->data){
            t->next = p1;
            t = p1;
            p1 = p1->next;
        }else{
            t->next = p2;
            t = p2;
            p2 = p2->next;
        }
    }
    while (p1!=NULL) {
        t->next = p1;t = p1;
        p1=p1->next;
    }

    while (p2!=NULL){
        t->next = p2;t = p2;
        p2 = p2->next;
    }
}

  

【2.8】同【2.6】代码

 

【2.9】

【题目大意】

无头结点的单链表两个
两个都是有序的
让你把这两个单链表合并成一个链表。
要求不能破坏第二个链表的结构

【做法】

在做归并的时候,如果第一个等于第二个,那么就跳过第二个链表遍历到的元素,这样第一个链表上有的元素,第二个链表里对应的就不会管他了。

无头结点不好直接在h1的基础上添加新的元素,所以自己另外创建一个无头结点的链表.一个一个累加上去就好。

【代码】

//这里必须要用二重指针,因为我们要改变第一个链表的指向(我们新创的一个链表)
//main函数里调用_merge(&h1,h2)即可(h2不用变)
void _merge(LNode **h1,LNode *h2){
    LNode *p1 = *h1;LNode *p2 = h2,*h3;
    h3 = newnode();//不好直接接在第一个链表上,所以新创建一个
    LNode *t = newnode();
    t = h3;
    while (p1!=NULL && p2!=NULL){
        if (p1->data<p2->data){
            LNode *temp = newnode(); //不能破坏原始链表,所以只能自己创了
            temp->data = p1->data;

            t->next = temp;
            t = temp;

            p1 = p1->next;
        }else if (p1->data>p2->data){
            LNode *temp = newnode();
            temp->data = p2->data;

            t->next = temp;
            t = temp;

            p2 = p2->next;
        }else if (p1->data==p2->data){
            //如果两个链表中有,那么只要第一个链表中的
            p2 = p2->next;
        }
    }
    if (p1==NULL) p1 = p2; //这样写比较简洁
    while (p1!=NULL) {
        LNode *temp = newnode();
        temp->data = p1->data;

        t->next = temp;t = temp;
        p1=p1->next;
    }

    *h1 = h3->next;//让h1再指向h3
}

  

【2.10】和【2.9的代码一样】只不过变成带头结点的了。遍历到两个链表的p和q的时候,如果p->data==q->data,则跳过其中一个就好了。

因为是集合,所以只会重复一次。

【2.11】

【题目大意】

求两个集合的交集(在两个链表里递增排列),

【做法】

也没说带不带头结点。。。就当做是有头结点吧。放在A链表中,这个简单,重构下A链表就好。

在归并的时候,如果p和q节点的节点值相同,就加到A链表的后面就好

【代码】

void _merge(LNode *h1,LNode *h2){
    LNode *p1 = h1->next;LNode *p2 = h2->next,*t;
    h1->next = NULL;
    t = h1;
    while (p1!=NULL && p2!=NULL){
        if (p1->data<p2->data){
            p1 = p1->next;
        }else if (p1->data>p2->data){
            p2 = p2->next;
        }else if (p1->data==p2->data){
            //如果两个链表中有,任取一个放在newA链表后面
            t->next = p1;
            t = p1;
            p1 = p1->next;
        }
    }
}

  

【2.12】和【2.11】一样的。

【2.13】也一样。。

【2.14】

题目大意:给你三个递增链表A,B,C让你求A∪(B∩C),时间复杂度要求为O(|A|+|B|+|C|)

 

posted @ 2019-09-23 11:33  AWCXV  阅读(503)  评论(0编辑  收藏  举报