Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
给定一个常数K和一个单链表L,你应该反向L上的每K个元素的链接。例如,给定L为1→2→3→4→5→6,如果K=3,那么你必须输出3→2→1→6→5→4;如果K=4,则必须输出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 N (≤105) which is the total number of nodes, and a positive K (≤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 N lines follow, each describes a node in the format:
输入规格:
每个输入文件包含一个测试用例。对于每一种情况,第一行包含第一个节点的地址,一个正的N(≤105)是节点的总数,一个正的K(≤N)是要反转的子列表的长度。节点地址为5位非负整数,NULL用-1表示。
接下来是N行,每一行描述一个节点,格式如下:Address Data Next
where
Address
is the position of the node,Data
is an integer, andNext
is the position of the next node.其中Address是节点的位置,Data是一个整数,Next是下一个节点的位置
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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
这道题大概意思就是,读入三个数字first、N、K,然后读入一个链表,首地址是first,长度N;读入顺序非结点顺序 ,读入数据中的address为本结点地址,next为下一个结点地址。要求:将该链表按照K个结点为一段,分别逆序;剩余结点不足K个,顺序输出。
这道题是曾经微软的一道面试题,由陈姥姥改造后,测试样例中加入了无用结点。也就导致排序逆序输出的同学挂了。(陈姥姥威武)。
1、建立一个长度为N的结构数组,读入N个结点的数据,并通过address和next将各结点排序,数组第一个元素是地址为first的结点,第二个为first的next,以此类推。可通过address和next的指向将无用结点排除掉,同时数组长度len--。
2、将排好序的数组,按照每K个进行翻转,也就是0和k-1互换,1和k-2互换直至两个下标相等或者重叠,注意len为奇数时,最后一次互换的下标相差2,偶数时下标相邻。
3、遍历数组输出。
代码如下:
#include
#include
typedef struct node{
int fadress;
int data;
int nadress;
}Node;
int N,K; //声明全局变量 N为链表长度,K为逆序长度
Node **read(); //读取函数 ,返回结构数组地址
int search(Node *array[],int k,int index); //搜索函数,index传入搜索开始的下标,返回目标结点下标
Node **reverse(Node **array); //翻转函数
void print(Node **array); //打印函数
int main(int argc,char const *argv[]){
Node **array=read();
print(array);
array=reverse(array);
print(array);
return 0;
}
int search(Node *array[],int k,int index){
int res=-1;
for(int i=index;ifadress){
res=i;
}
}
return res;
}
Node **read(){
int first;
scanf("%d%d%d",&first,&N,&K);
Node **array=(Node**)malloc(sizeof(Node*)*N); //创建结构指针数组,元素为结构体指针
FILE *fp=fopen("test.txt","r"); //用文件读入数据,方便自己测试
int head=0;
for(int i=0;ifadress,&array[i]->data,&array[i]->nadress);
if(array[i]->fadress==first) head=i; //记录头结点的下标
}
fclose(fp);
Node *ptemp=array[head]; //将头结点放在下标为0的位置
array[head]=array[0];array[0]=ptemp;
for(int i=1;inadress,i);//i以前已排好序,从i向后搜索(i-1)的next
if(temp!=-1){
array[i]=array[temp];
array[temp]=ptemp;
}else{ //返回-1说明下标i-1位置结点为链表尾部,结点数为i
N=i; //N=i,数组N缩短,去除无效下标。
}
}
return array;
}
void print(Node **array){
for(int i=0;ifadress,array[i]->data);
if(array[i]->nadress!=-1) printf("%-.5d\n",array[i]->nadress);
else printf("%d\n",array[i]->nadress);
}
}
Node **reverse(Node **array){
int i,j;
int cnt=N/K; //数组N里面有cnt个K,也就是分cnt段翻转;i为段首,j为段末
for(i=0,j=i+K-1;i0) array[i-1]->nadress=array[i]->fadress;//对调后,如果不是第一个元素,需要将next地址链接起来
}
if(cnt*K!=N) array[cnt*K-1]->nadress=array[cnt*K]->fadress;//cnt*K!=N,有剩余结点需链接上。
array[N-1]->nadress=-1; //将数组最后一个元素的next设为-1,为链表尾。
return array;
}
1、创建一个长度为最大N的结构指针数组array[MAXN]也就是长度为10e5,读入每个结点,地址为数组下标,next指向下一个结点的下标。创建Node *plist=array[first];利用下标将每个结点链接起来,array[i]=array[array[i]->naddress]。
2、先实现一个段的翻转。利用三个指针分别指向链表的首New、第二个old、第三个ptemp结点。
p=plist,临时保存首结点。old->next=New;New=old;old=ptemp,循环K次,p->next=old;完成一次K个结点的翻转,并链接到后续结点。
3、将整个链表需要翻转的结点分为cnt段,cnt=N/K。循环cnt次,将每段翻转。
代码如下:
#include
#include
typedef struct node Node;
typedef int ElementType;
struct node{
int index;
ElementType data;
int nadress;
Node *next;
};
#define MAX 100001
int n; //声明全局变量n
Node *read(int first); //读入函数
Node *reverse(Node *plist,int k); //逆序函数,返回逆序后的头结点地址
void print(Node *plist); //打印函数
int main(int argc,char const *argv[]){
int first,k;
scanf("%d%d%d",&first,&n,&k);
Node *plist=read(first);
int cnt=n/k; //链表内有cnt个K,
Node *ptemp=plist,*p=plist; //ptemp指向当前段的段首
/*此循环如果被放在reverse函数内,运行超时*/
for(int i=0;inext=ptemp;p->nadress=ptemp->index;//将处理后的段,链接到上个段的末尾
p=q; //将p指向当前段的段尾
}
ptemp=p->next; //ptemp指向下个段首
}
print(plist);
return 0;
}
Node *read(int first){
Node *array[MAX]; //设置长度为MAX的结构指针数组
Node *plist=NULL; //定义链表头指针
// FILE *pf=fopen("test.txt","r"); //从文件读取数据,方便自己测试,可删除
for(int i=0;idata,&array[index]->nadress);
array[index]->index=index;
if(index==first) plist=array[index];
}
// fclose(pf);
Node *p=plist; //下面循环是利用结构体内内部index和nadress将链表链接起来
for(p=plist,n=1;p->nadress!=-1;p->next=array[p->nadress],p=p->next,n++);
p->next=NULL; //此时p是链表末尾结点,n是链表中有效结点数量。
return plist;
}
Node *reverse(Node *plist,int k){
Node *p=plist,*ptemp=NULL;
Node *New=plist,*old=New->next;
while(k>1){
ptemp=old->next; //New为链表头,old为第二个结点,ptemp为第三个结点
old->next=New; //old指向New,new,old,和ptemp逐一向后移
old->nadress=New->index; //k控制向后移动的距离
New=old,old=ptemp;
k--;
}
p->next=old; //记录逆序前的首结点,逆序完成后变为末结点,指向后续结点
if(old){
p->nadress=old->index; //后续结点为不为空时,更新p的nadress
}else{
p->nadress=-1; //后续结点为空时,p为链表的末结点,p的nadress设为-1;
}
return New; //函数返回逆序后,段的头结点。
}
void print(Node *plist){
for(Node *p=plist;p;p=p->next){
printf("%.5d %d ",p->index,p->data,p->nadress);
if(p->nadress!=-1) printf("%.5d\n",p->nadress);
else printf("%d\n",p->nadress);
}
}
/*将分段的循环放入reverse函数内部,测试数据最大N运行超时
Node *reverse(Node *plist){
Node *p=plist,*ptemp=NULL;
Node *New=plist,*old=New->next;
for(int i=0;i1){
ptemp=old->next;
old->next=New;
old->nadress=New->index;
New=old;old=ptemp;
j--;
}
if(i==0){
plist=New;
p->next=old;
if(old){
p->nadress=old->index;
New=old;old=New->next;
}else{
p->nadress=-1;
}
}else{
p->next=New;p->nadress=New->index;
if(old){
New=old;old=New->next;
}else{
q->next=NULL;
q->nadress=-1;
}
p=q;
}
}
return plist;
}*/