团体天梯练习 L2-022 重排链表

发布时间 2023-04-18 16:36:59作者: Amαdeus

L2-022 重排链表

给定一个单链表 \(L_{1}\)\(L_{2}\) → ⋯ → \(L_{n−1}\)\(L_{n}\) ,请编写程序将链表重新排列为 \(L_{n}\)\(L_{1}\)\(L_{n−1}\)\(L_{2}\) → ⋯
例如:给定 \(L\) 为 1→2→3→4→5→6 ,则输出应该为 6→1→5→2→4→3 。

输入格式:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数 \(N\) ( \(≤10^{5}\) )。结点的地址是5位非负整数,\(NULL\) 地址用−1表示。

接下来有 \(N\) 行,每行格式为:

\(Address\) \(Data\) \(Next\)
其中 \(Address\) 是结点地址;\(Data\) 是该结点保存的数据,为不超过 \(10^{5}\) 的正整数;\(Next\)是下一结点的地址。题目保证给出的链表上至少有两个结点。

输出格式:

对每个测试用例,顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例:

68237 6 00100
00100 1 99999
99999 5 12309
12309 2 00000
00000 4 33218
33218 3 -1


解题思路

这是一道关于链表构造的数据结构题,我先用链式前向星把原始链表建立起来,然后用两个数组分别顺序存储所有的节点值地址数值。之后的操作其实还是比较简单的,题中要求构建的链表,可以发现奇数位是从原始链表的最后一个节点开始依次递减的(即第n个,然后第n-1个...),偶数位是从原始链表的第一个节点开始依次递增的(即第1个,然后是第2个...)。采用一种双指针算法,就可以解决这个问题,假设顺序存储的地址数值一共有 \(t\) 个,那么左指针指向下标 \(0\),右指针指向下标 \(t-1\),然后双向操作直到最后所有数值用完,在操作过程中保持地址一致。当所有节点用完时,最后一个节点需要单独处理一下,末地址赋值为 \(-1\)

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, int> psi;
typedef __int128 int128;
#define PI acos(-1.0)
#define x first
#define y second
//int dx[4] = {1, -1, 0, 0};
//int dy[4] = {0, 0, 1, -1};
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;


const int N = 1e5 + 10;
int h, e[N], ne[N], idx; 
int n, idxs[N], ele[N];   //存储地址 存储元素

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    cin >> h >> n;
    for(int i = 0; i < n; i ++ ){
        int idx, x, nex; cin >> idx >> x >> nex;
        e[idx] = x, ne[idx] = nex;
    }

    int t1 = 0, t2 = 0;
    for(int i = h; ~i; i = ne[i]){
        idxs[t1 ++ ] = i;         //顺序存储地址
        ele[t2 ++ ] = e[i];       //顺序存储节点值
    }

    int cur = 0, l = 0, r = t1 - 1;    //l从前往后 r从后往前
    while(t1 -- ){
        cur ++ ;
        if(cur & 1){   //奇数 从后往前
            if(t1 == 0) printf("%05d %d -1\n", idxs[r], ele[r]);    
            else{
                printf("%05d %d %05d\n", idxs[r], ele[r], idxs[l]);
                r -- ;
            }
        }else{         //偶数 从前往后
            if(t1 == 0) printf("%05d %d -1\n", idxs[l], ele[l]);
            else{
                printf("%05d %d %05d\n", idxs[l], ele[l], idxs[r]);
                l ++ ;
            }
        }
    }

    return 0;
}