PAT(甲级)2019年秋季考试 7-2 Merging Linked Lists (25 分)凌宸1642

PAT(甲级)2019年秋季考试 7-2 Merging Linked Lists (25 分)

题目描述:

Given two singly linked lists L1=a1→a2→⋯→an−1→an and L2=b1→b2→⋯→bm−1→bm. If n≥2m, you are supposed to reverse and merge the shorter one into the longer one to obtain a list like a1→a2→bm→a3→a4→bm−1⋯. For example, given one list being 6→7 and the other one 1→2→3→4→5, you must output 1→2→7→3→4→6→5.

译:给定两个单链表 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。


Input Specification (输入说明):

Each input file contains one test case. For each case, the first line contains the two addresses of the first nodes of L1 and L2, plus a positive N (≤105) which is the total number of nodes given. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is a positive integer no more than 105, and Next is the position of the next node. It is guaranteed that no list is empty, and the longer list is at least twice as long as the shorter one.

译:每个输入文件包含一个测试用例,对于每种情况,第一行包含表示L1 和 L2 的首节点的地址,再加上一个表示给出结点总数的正整数 N (≤105) 。一个结点的地址是一个 5 位的非负数,并且空节点用 -1 表示。

接下来 N 行,每行用如下格式描述一个结点:

Address Data Next

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


Output Specification (输出说明):

For each case, output in order the resulting linked list. Each node occupies a line, and is printed in the same format as in the input.

译:对于每种情况,将结果链表依次输出。每个结点占一行,格式和输入格式相同。


Sample Input (样例输入):

00100 01000 7
02233 2 34891
00100 6 00001
34891 3 10086
01000 1 02233
00033 5 -1
10086 4 00033
00001 7 -1

Sample Output (样例输出):

01000 1 02233
02233 2 00001
00001 7 34891
34891 3 10086
10086 4 00100
00100 6 00033
00033 5 -1

The Idea:

题目中明确说明了,两个链表是有长有短的,而且长的链表的长度 n 和短的链表的长度 m 一定满足 n >= 2m

需要注意的地方:

  • 并没有指明哪个是长链表,哪个是短链表
  • 并不是给出的所有结点,都是链表上的节点(存在无效节点,最后两个测试点)

我的思路是用结构体模拟链表,然后因为合并的时候,是隔两个加一个,而且加的是逆序,可以选择先将短链表翻转过来,但是这里我选择了使用 , 这样很方便进行取出需要添加的节点。


The Codes:

#include<bits/stdc++.h>
using namespace std ;
const int maxn = 100010 ;

struct node{
	int data , next ;
}link[maxn] ;

int l1 , l2 , n , id , ans ;

void merge(int start , stack<int> st){
	ans = start ; // 记录最后的合并后的起始地址
	for(int i = 0 ; !st.empty() ; i ++){
		if(i > 0 && (i + 1) % 2 == 0){
			int top = st.top() ;
			st.pop() ;
			link[top].next = link[start].next ;
			link[start].next = top ;
			start = link[top].next ;
		}else start = link[start].next ;
	}
}
int main(){
	scanf("%d%d%d" , &l1 , &l2 , &n) ;
	
    for(int i = 0 ; i < n ; i ++){
		scanf("%d" , &id) ;
		scanf("%d%d" , &link[id].data , &link[id].next) ;
	}
	
    int p = l1 , q = l2 ;
	stack<int> st1 , st2 ;
	while(p != -1 && q != -1){ // 将短链表的所有结点全部 入栈
		st1.push(p) ;
		p = link[p].next ;
		st2.push(q) ;
		q = link[q].next ;
	}
    
	if(p == -1) merge(l2 , st1) ; // 如果 l1 是短链,则将 l1  合并到 l2 中
	else merge(l1 , st2) ; // 如果 l2 是短链,则将 l2  合并到 l1 中
	
    while(link[ans].next != -1){ // 不是 n 个,因为有无效节点
		printf("%05d %d %05d\n" , ans , link[ans].data , link[ans].next) ;
		ans = link[ans].next ;
	}
	printf("%05d %d -1\n" , ans , link[ans].data) ;
	return 0 ;
}

用数组的前后关系模拟链表的前后结点,这种思路值得借鉴!!!

#include<bits/stdc++.h>
using namespace std;
struct node {
    int data, addr;
};
node nodes[100005];

int main() {
    int headA, headB, n;
    cin >> headA >> headB >> n;

    for (int i = 0; i < n; ++i) {
        int address, data, next;
        cin >> address >> data >> next;
        nodes[address] = {data, next};
    }

    vector<node> a, b, c;
    for (int p = headA; p != -1; p = nodes[p].addr) 
        a.push_back({nodes[p].data, p});
    for (int p = headB; p != -1; p = nodes[p].addr)
        b.push_back({nodes[p].data, p});

    if (a.size() < b.size()) swap(a, b);
    reverse(b.begin(), b.end());
    for (int i = 0, j = 0, k = 0; i < a.size() || j < b.size(); ++k) {
        if (k % 3 == 2 && j < b.size()) c.push_back(b[j++]);
        else c.push_back(a[i++]);
    }

    for (int i = 0; i < c.size(); ++i) {
        printf("%05d %d ", c[i].addr, c[i].data);
        if (i == c.size() - 1) cout << "-1\n";
        else printf("%05d\n", c[i + 1].addr);
    }
}

The result :

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lingchen0522

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

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

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

打赏作者

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

抵扣说明:

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

余额充值