PTA || 02-线性结构3 Reversing Linked List
Given a constant KKK and a singly linked list LLL, you are supposed to reverse the links of every KKK elements on LLL. For example, given LLL being 1→2→3→4→5→6, if K=3K = 3K=3, then you must output 3→2→1→6→5→4; if K=4K = 4K=4, you must output 4→3→2→1→5→6.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive NNN (≤105\le 10^5≤105) which is the total number of nodes, and a positive KKK (≤N\le N≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then NNN lines follow, each describes a node in the format:
Address Data Next
where Address
is the position of the node, Data
is an integer, and Next
is the position of the next node.
Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
做这个题目的过程好艰难!!!!我就不说花了多久了,瞬间觉得自己是个菜鸡菜鸡大菜鸡。刚开始题目题意都没有看清,看掉every K前面的every,天哪,当时还心想这题真TM简单只用一次逆转就行居然还是微软面试改编我是不是写完这题就能走上人生巅峰(简直就是做梦)
每K长度逆转的关键在于:
- 前一段已经逆转的K长度子链表尾结点要与后面还未逆转的链表头结点相连
- 在后一段K长度子链表逆转完成后,前一段已经逆转的K长度子链表尾结点要与后一段已经逆转的K长度子链表头结点相连
- 完成所有逆转后,已经逆转完成的链表段尾结点要与后面不需要进行逆转的剩余链表头结点相连,最后输出
需要注意的是:对于一段已经逆转的子链表段来说,逆转完成后的链表尾结点就是该链表还没有逆转时的头结点,换言之未逆转链表的头结点将是下一阶段已逆转链表的尾结点。所以说,这个结点就只有一个、只有这唯一一个,既是头结点也是尾结点。想明白了就觉得自己是傻叉,这么明显会有被覆盖的危险难道不要避免吗!怎么避免呢!当然是存两遍啊!难道留着回家过年啊!当然是一个用来留着当新表头,告诉你这个傻叉,喂!你到底逆转好了吗!你可要记住我才是这个新链表的头儿,要遍历要输出得我这儿说了算;另一个呢,用来存着当新链表的尾巴,后面该接啥接啥!
关键代码片段!!!!!
LastHead = Head;
Head = List[Head].Next;
……
……
List[LastHead].Next = New;
List[Head].Next = Old;
读懂了上面那段话,就能看懂上面几行代码啥意思了。
#include <stdio.h>
#include <stdlib.h>
#define ElementType int
#define MaxAddress 100002
struct Node {
ElementType Data;
int Next;
}List[MaxAddress];
//主体程序框架
/****************************************************
1.读入并形成链表
·当有多余结点时(N>K且cnt=0),直接在逆转链表后面读出
·当N=K时(cnt=1),完全逆转
·当N=nK时(N>K且cnt!=0),每K个链表长度逆转一次
2.逆转链表
3.写链表
****************************************************/
void readList(struct Node List[], int N);
int countNum(int N, int FirstNode);//计算有效链表长度
int reverseList(int FirstNode, int cnt, int K);
void WriteList(int Head);
int main()
{
int FirstNode, N, K, H;
int cnt;
scanf("%d %d %d", &FirstNode, &N, &K);
//cnt = N / K;
readList(List, N);
N = countNum(N, FirstNode);
cnt = N / K;
H = reverseList(FirstNode, cnt, K);
WriteList(H);
}
void readList(struct Node List[], int N)
//读入并形成链表
{
int i, adr;
for (i = 0; i<N; i++){
scanf("%d ", &adr);
scanf("%d %d", &List[adr].Data , &List[adr].Next );
}
}
int countNum(int N, int FirstNode)//计算有效链表的长度,为了通过多余结点这个测试点
{
int Temp = FirstNode;
int count = 1;
while (List[Temp].Next != -1){
count++;
Temp = List[Temp].Next ;
}
return count;
}
int reverseList(int FirstNode, int cnt, int K)
{
int New, Old, Temp, Temp_2, LastHead;
int Head = 100001;
List[Head].Next = FirstNode;
if (cnt == 1){
New = List[Head].Next ;
Old = List[New].Next ;
Temp = List[Old].Next ;
for (int i = 0; i < K-1; i++){
List[Old].Next = New;
New = Old;
Old = Temp;
Temp = List[Old].Next ;
}
List[List[Head].Next ].Next = Old;//完成一次K链表长度的逆转,后面有多余结点
List[Head].Next = New;
}else{
//cnt=n
for (int i = 0; i < cnt; i++){
LastHead = Head ;//LastHead指向上一段已逆转链表的尾结点
Head = List[Head].Next ;//head此时是未逆转链表的头结点,此时未逆转链表头结点将是下一阶段已逆转链表的尾结点
New = Head;
Old = List[New].Next ;
Temp = List[Old].Next ;
for (int j = 0; j < K-1; j++){
List[Old].Next = New;
New = Old;
Old = Temp;
Temp = List[Old].Next ;
}//到这里,head是已逆转链表的尾结点
if (i == 0){//第一次逆转
List[List[LastHead].Next ].Next = Old;//Old是未逆转链表头结点
Temp_2 = New;
}
else{
List[LastHead].Next = New;
List[Head].Next = Old;
}
}
Head = 100001;//初始化空表头结点
List[Head].Next = Temp_2;
}
return Head;
}
void WriteList(int Head)
{
Head = List[Head].Next ;
while (Head != -1){
if (List[Head].Next == -1)
printf("%05d %d %d\n", Head, List[Head].Data , List[Head].Next );
else
printf("%05d %d %05d\n", Head, List[Head].Data , List[Head].Next );
Head = List[Head].Next ;
}
}