PAT (Basic Level) Practice 1025 反转链表题解思路

这题是把n个结点的链表,每k个数反转,而且最后不足k个数不反转。

比如给定L为1→2→3→4→5→6,K为3,则输出应该为3→2→1→6→5→4;如果K为4,则输出应该为4→3→2→1→5→6

然后这里的链表给出结点地址,数据,及下一节点的地址,格式如下

00000 4 99999

一开始没思路,自己写了个很烂的代码,只能通过一个case。后来搜索解题思路,大致是用一个数组存入所有结点,然后按起始地址,顺序重排所有结点,最后每k个结点反转。

用一个结构体来定义结点

typedef struct
{
    int addr;
    int data;
    int next;
}List,*pList;

数组用new申请一个堆空间,因为题目结点上限是10w个

pList pl = new List[100000]();

数据输入部分用scanf提高时间效率

然后按每个节点的起始地址存入到数组中,好处是可以利用数组O(1)的复杂度,瞬间访问到某个结点,而不用遍历整个数组

List t;
for ( i=0 ; i < n ; ++ i )
{
    scanf("%d%d%d",&t.addr,&t.data,&t.next);
    pl[t.addr]=t;
}

按链表起始结点,让所有结点有序,直到最后一个结点,这里用了STL的Vector数据结构存储有序的链表

vector<List> v;
while(beg!=-1)
{
    v.push_back(pl[beg]);
    beg=pl[beg].next;//更新为下一节点的起始地址 
}

翻转链表,就是把k个结点入栈,再出栈存到新的向量中;如果剩余不足k个数,则顺序存入向量中

记得还要修正next地址,就是让翻转后的链表结点next地址正确。这一步不必在翻转的代码中做,只要在最后打印输出的时候,把next地址修改为下一节点的起始地址

完整代码如下

#include <iostream>
#include <vector>
#include <stack>
#include <stdio.h>
using namespace std;

typedef struct
{
	int addr;
	int data;
	int next;
}List,*pList;

int main()
{	
	vector<List> v,v2;
	pList pl = new List[100000]();//用一个数组存储数据
	List t;
	int beg;
	int n,k,i;
	cin >> beg >> n >> k;

	for ( i=0 ; i < n ; ++ i )
	{
		//cin >> pl[i].addr >> pl[i].data >> pl[i].next ;
		scanf("%d%d%d",&t.addr,&t.data,&t.next);
		pl[t.addr]=t;//让每个节点的起始地址直接作为数组的下标
	}
	if(beg == -1) //首地址为-1.直接输出  
    {  
        printf("-1\n");  
        return 0; 
    }  
    //用一个vector按开始地址顺序存储链表,否则用暴力法双重循环查找链表的起始地址超时 
	while(beg!=-1)
	{
		v.push_back(pl[beg]);
		beg=pl[beg].next;//更新为下一节点的起始地址 
	} 
	
	//每k个一组,将向量数据入栈,再出栈,存入新的向量
	//auto it = v.begin();
	vector<List>::iterator it=v.begin();
	for ( ; it != v.end() ; )
	{
		stack<List> s;
		if(v2.size()+k <= v.size())//要有k个数才逆转链表
		{
			for (i=0;i<k;++i)
			{
				s.push(*it);
				++it;
			}
			while(!s.empty())
			{
				List temp = s.top();
				s.pop();
				v2.push_back(temp);
			}
		}else{
			v2.push_back(*it);//小于k个数,不逆转,直接存入向量
			++it;
		}
	}
	

	//输出
	it = v2.begin();
	for ( ; it != v2.end()-1 ; ++it)
	{
		it->next=(it+1)->addr;//修正逆转后的链表的next地址
		printf("%05d %d %05d\n" , it->addr ,it->data ,it->next);
	}
	it->next=-1;
	printf("%05d %d %d\n" , it->addr ,it->data ,it->next);
	
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/lnmay36/p/9278523.html