2019秋季PAT乙级真题--7-5 链表合并 (25 分)

7-5 链表合并 (25 分)

给定两个单链表 L1=a1→a2→⋯→an−1→an 和 L2=b1→b2→⋯→bm−1→bm。如果 n≥2m,你的任务是将比较短的那个链表逆序,然后将之并入比较长的那个链表,得到一个形如 a1→a2→bm→a3→a4→bm−1⋯ 的结果。例如给定两个链表分别为 6→7 和 1→2→3→4→5,你应该输出 1→2→7→3→4→6→5。

输入格式:

输入首先在第一行中给出两个链表 L1 和 L2 的头结点的地址,以及正整数 N (≤105),即给定的结点总数。一个结点的地址是一个 5 位数的非负整数,空地址 NULL 用 -1 表示。

随后 N 行,每行按以下格式给出一个结点的信息:

Address Data Next

其中 Address 是结点的地址,Data 是不超过 105 的正整数,Next 是下一个结点的地址。题目保证没有空链表,并且较长的链表至少是较短链表的两倍长。

输出格式:

按顺序输出结果链表,每个结点占一行,格式与输入相同。

输入样例:

00100 01000 7

02233 2 34891

00100 6 00001

34891 3 10086

01000 1 02233

00033 5 -1

10086 4 00033

00001 7 -1

输出样例:

01000 1 02233

02233 2 00001

00001 7 34891

34891 3 10086

10086 4 00100

00100 6 00033

00033 5 -1

解:
本题常规链表处理题,按照题目的意思,一定是一个链表长一个短,要将短的插入到长的里面去,规律是每间隔长链表中的两个元素后插入一个短链表元素,常规struct+list解法,struct中只需要存data与next,list的下标即是每一个node的首地址,相当于散列表,注意短表需要整体翻转->reverse(),其中判断长短表的方法是使用iostream头文件下的swap函数,我的目的是让vt[0]中存的链表永远是最短的链表,这里解释一下,swap中可以传入vector类型

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1e5+10;
struct node{
    int data;
    int next;
}list[maxn];

int main() {
    int first1, first2, n;
    cin >> first1 >> first2 >> n;
    while (n--) {
        int temp;
        cin >> temp;
        cin >> list[temp].data >> list[temp].next;
    }
    vector<int> vt[2];
    while (first1 != -1) {
        vt[0].push_back(first1);
        first1 = list[first1].next;
    }
    while (first2 != -1) {
        vt[1].push_back(first2);
        first2 = list[first2].next;
    }
    if (vt[0].size() > vt[2].size())
        swap(vt[0], vt[1]);
    reverse(vt[0].begin(), vt[0].end());
    int cnt = 0, temp = 0;
    for (int i = 0; i < vt[1].size(); ++i) {
        cnt++;
        if (cnt == 3 && temp < vt[0].size()) {
            cnt = 0;
            vt[1].insert(vt[1].begin() + i, vt[0][temp++]);
        }
    }
    int key = 0;
    for (auto it:vt[1]) {
        if (key == 0) {
            printf("%05d %d ", it, list[it].data);
            key = 1;
        } else {
            printf("%05d\n%05d %d ", it, it, list[it].data);
        }
    }
    cout << -1;
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 题目描述 将两个单调递增的链表合并为一个单调不减的链表,例如链表1为1->3->5->7,链表2为2->4->6->8,则合并后的链表应该为1->2->3->4->5->6->7->8,链表节点定义如下: struct ListNode { int val; struct ListNode *next; }; 函数定义 struct ListNode* merge(struct ListNode* pHead1, struct ListNode* pHead2); 输入参数 - pHead1: 链表1的头结点 - pHead2: 链表2的头结点 输出参数 - 返回合并后的链表头结点 样例 输入: 链表1: 1->3->5->7 链表2: 2->4->6->8 输出: 合并后的链表: 1->2->3->4->5->6->7->8 解题思路 这道题可以用递归或者迭代两种方法来解决。 递归方法 递归方法的思路是,比较两个链表的头结点,将较小的头结点作为合并后链表的头结点,然后递归地合并剩余的链表。 迭代方法 迭代方法的思路是,用一个指针p指向合并后链表的尾结点,然后比较两个链表的头结点,将较小的头结点接到p的后面,然后将p指向新的尾结点,继续比较两个链表的头结点,直到其中一个链表为空,然后将另一个链表接到合并后链表的尾部。 参考代码 递归方法 struct ListNode* merge(struct ListNode* pHead1, struct ListNode* pHead2) { if (pHead1 == NULL) { return pHead2; } if (pHead2 == NULL) { return pHead1; } if (pHead1->val < pHead2->val) { pHead1->next = merge(pHead1->next, pHead2); return pHead1; } else { pHead2->next = merge(pHead1, pHead2->next); return pHead2; } } 迭代方法 struct ListNode* merge(struct ListNode* pHead1, struct ListNode* pHead2) { if (pHead1 == NULL) { return pHead2; } if (pHead2 == NULL) { return pHead1; } struct ListNode* p = NULL; if (pHead1->val < pHead2->val) { p = pHead1; pHead1 = pHead1->next; } else { p = pHead2; pHead2 = pHead2->next; } struct ListNode* head = p; while (pHead1 != NULL && pHead2 != NULL) { if (pHead1->val < pHead2->val) { p->next = pHead1; pHead1 = pHead1->next; } else { p->next = pHead2; pHead2 = pHead2->next; } p = p->next; } if (pHead1 != NULL) { p->next = pHead1; } if (pHead2 != NULL) { p->next = pHead2; } return head; }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苯酸氨酰糖化物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值