(模拟)L2-2 重排链表

 

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

输入格式:

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

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

Address Data Next

其中Address是结点地址;Data是该结点保存的数据,为不超过1的正整数;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

题解:个人感觉选好存储结构很关键。

#include<iostream>
using namespace std;
const int maxn=100001;
struct LNode{
    int data,next;
}Node[maxn];
int a[maxn],b[maxn];//a数组依次存储链表中的结点地址,b数组存储重排后的结点地址

int main()
{
    int index,n,t;
    scanf("%d%d",&index,&n);
    for(int i=0;i<n;i++)
    {
        cin>>t;
        cin>>Node[t].data>>Node[t].next;
    }
    int r=0;
    a[r++]=index;
    t=Node[index].next;
    while(t!=-1)
    {
        a[r++]=t;
        t=Node[t].next;
    }
    int left=0,right=r-1;
    r=0;
    while(left<=right)
    {
        b[r++]=a[right--];
        if(left<=right)
            b[r++]=a[left++];
    }
    for(int i=0;i<r;i++)
    {
        if(i!=r-1)
            printf("%05d %d %05d\n",b[i],Node[b[i]].data,b[i+1]);
        else
            printf("%05d %d -1\n",b[i],Node[b[i]].data);
    }
    return 0;
}

2019/3/19 如今的思路: 

#include<cstdio>
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;

struct Node{
	int ad,next,data;
}mes[maxn],ans[maxn];

int main(){
	int f,n,a;
	scanf("%d%d",&f,&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a);
		scanf("%d%d",&mes[a].data,&mes[a].next);
	}
	int r=1;
	while(f!=-1){
		ans[r].ad=f;
		ans[r++].data=mes[f].data;
		//printf("f=%05d\n",f);
		f=mes[f].next;
	}
	for(int i=1;i<r;i++){
		if(i%2==1)
			mes[i]=ans[r-1-i/2];
		else 
			mes[i]=ans[i/2];
	}
	for(int i=1;i<r-1;i++){
		printf("%05d %d %05d\n",mes[i].ad,mes[i].data,mes[i+1].ad);
	}
	printf("%05d %d -1\n",mes[r-1].ad,mes[r-1].data);
	return 0;
}

 

 

<think>嗯,用户问的是L2-022重排链表的测试点3的问题。首先,我需要回忆一下这个题目的具体要求。根据引用[2]和[3],题目要求将链表重新排列成类似Ln→L1→Ln-1→L2这样的顺序。比如输入12→3→4→5→6,输出应该是6→1→5→2→4→3。测试点3可能有一些特殊情况,导致用户的代码无法通过。 常见的测试点问题可能包括边界情况,比如链表长度为奇数或偶数的情况,或者处理链表末节点的指针没有正确设置为-1。根据引用[3]中的样例,输出中最后一个节点的next是-1,所以需要确保在重组链表后,最后一个节点的next正确。 另外,用户提到的测试点3可能涉及链表节点数量为奇数的情况,或者中间节点的处理问题。比如在分割链表为前后两半时,如果链表长度是奇数,后半部分的起点可能需要特别处理。例如,当链表长度为5时,前半部分可能是前2个节点,后半部分是后3个?或者反过来?这时候分割点的选择是否正确就很重要。 还有一种可能是在反转链表时出错。题目通常需要将后半部分反转,然后合并到前半部分。如果反转过程中指针处理不当,可能导致节点丢失或者循环链表的问题,进而导致测试点3失败。例如,反转后的链表头是否正确,或者反转过程中是否遗漏了某些节点的next指针的调整。 此外,输入中可能存在无效节点,即虽然输入了多个节点,但有些节点并不在初始链表中。例如,头结点给出的地址可能存在,但后续节点可能有不在链表中的情况。因此,构建链表时需要先遍历头结点,并过滤掉无效的节点,确保链表的正确长度。如果用户没有处理这种情况,测试点3可能包含这样的无效节点,导致链表长度计算错误,进而影响后续的分割和反转操作。 例如,在代码中,用户可能直接从输入的所有节点中构建链表,而没有根据起始地址遍历,导致包含了不在链表中的节点。这会改变链表的实际长度,导致分割错误。比如,实际有效节点是6个,但因为没有过滤,可能处理了更多的节点,导致后半部分错误。 另外,在合并两个链表时,尤其是当后半部分比前半部分长的时候(比如链表长度为奇数),需要确保每一步的指针连接正确。例如,当合并到最后一个节点时,可能没有正确设置其next为-1,或者中间的某个节点的next指向错误,导致输出不符合预期。 可能的解决方法是检查链表的构建是否正确,确保过滤了无效节点。然后检查分割链表的位置是否正确,比如总长度是否为偶数或奇数,并正确处理中间节点。接着,确保反转后半部分链表的过程无误,尤其是在处理指针反转时的顺序。最后,合并两个链表时,交替连接节点,并处理最后的剩余节点,确保末尾节点的next为-1。 例如,用户可能没有正确计算链表的长度,导致分割错误。例如,链表实际长度为n,分割点应该是n/2的位置,但可能用户错误地计算为(n+1)/2,导致后半部分长度不正确。或者,在反转链表时,没有正确反转,导致后半部分的顺序错误。 此外,测试点3可能涉及到较大的数据量,或者某些特殊的数据结构,比如节点地址的格式是否正确输出,比如必须保留前导零,例如地址是五位数字,输出时必须补零,否则也会导致错误。例如,节点地址是00100,输出时如果变成100,就会出错。这可能是用户代码中的格式化问题,比如使用%d而不是%05d来输出地址,导致测试点3失败。 总结可能的错误原因包括:链表构建时未过滤无效节点、链表分割位置错误、后半部分反转不正确、合并过程中的指针连接错误,以及输出格式问题。解决方案需要逐一排查这些问题,特别是确保链表的正确构建和分割,反转的正确性,以及输出的格式正确。</think>### L2-022 重排链表测试点3的解决方案 测试点3通常考察**链表长度处理**和**指针重置**的边界情况。根据题目要求[^2][^3],以下是常见错误原因及解决方法: --- #### 一、常见错误原因 1. **无效节点未过滤** - 输入数据中可能存在**不在链表中的冗余节点**,若未根据起始地址遍历链表,会导致实际链表长度计算错误[^3] - 示例:输入包含6个节点,但实际链表可能只有4个有效节点 2. **链表分割位置错误** -链表长度为**奇数**时,后半部分起点应为 `总长度//2 + 1`,若分割点计算错误会导致后续操作异常 - 示例:链表长度5时,前半部分2个节点,后半部分3个节点 3. **末节点指针未重置** - 重排链表的最后一个节点必须设置 `next` 为 `-1`,否则输出格式错误 4. **地址格式化问题** - 输出时未使用 `%05d` 格式化地址(如 `00100` 错误输出为 `100`) --- #### 二、解决方案与代码实现 ##### 关键步骤: 1. **构建有效链表** ```python head, n, _ = input().split() # 读取起始地址和总节点数 nodes = {} # 用字典存储所有节点 for _ in range(int(n)): addr, data, next_addr = input().split() nodes[addr] = (data, next_addr) # 构建实际链表(过滤无效节点) valid_list = [] current = head while current != '-1': valid_list.append((current, nodes[current][0])) current = nodes[current][1] ``` 2. **分割链表并反转后半部分** ```python mid = len(valid_list) // 2 first_half = valid_list[:mid] second_half = valid_list[mid:][::-1] # 反转后半部分 ``` 3. **交替合并链表** ```python result = [] for i in range(len(second_half)): result.append(second_half[i]) if i < len(first_half): result.append(first_half[i]) # 处理奇数长度情况 if len(valid_list) % 2 != 0 and len(first_half) > len(second_half): result.append(first_half[-1]) ``` 4. **重置指针并格式化输出** ```python for i in range(len(result)-1): print(f"{result[i][0]} {result[i][1]} {result[i+1][0]}") print(f"{result[-1][0]} {result[-1][1]} -1") # 末节点next置为-1 ``` --- #### 三、测试点3验证要点 1. **输入数据验证** 检查输入样例中是否存在类似以下情况: ``` 00100 6 00000 4 99999 # 可能被过滤的无效节点 00100 1 12309 # 有效节点 68237 6 -1 # 有效节点 33218 3 00000 99999 5 68237 12309 2 33218 ``` 2. **输出格式验证** 确保输出地址保留前导零(如 `00100` 而非 `100`),末节点 `next` 为 `-1`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值