PAT 1165 Block Reversing 思维量小的解法

个人学习记录,代码难免不尽人意。

Given a singly linked list L. Let us consider every K nodes as a block (if there are less than K nodes at the end of the list, the rest of the nodes are still considered as a block). Your job is to reverse all the blocks in L. For example, given L as 1→2→3→4→5→6→7→8 and K as 3, your output must be 7→8→4→5→6→1→2→3.

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 (≤10 5 ) which is the total number of nodes, and a positive K (≤N) which is the size of a block. 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:

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 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218
Sample Output:
71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1

#include 
#include
#include
#include
#include
#include 
#include
using namespace std;
const int maxn=100010;

struct node{
	int address;
	int data;
	int next;
}Node[maxn];

int nextnode[maxn];
stack<vector<int> > s;
stack<vector<int> > temp;
int main(){
     int begin,n,k;
     scanf("%d %d %d",&begin,&n,&k);
     for(int i=0;i<n;i++){
     	int address,data,next;
     	scanf("%d %d %d",&address,&data,&next);
     	Node[address].address=address;
     	Node[address].data=data;
     	Node[address].next=next;
	 }
	 int op=begin;
	 int count=0;
	vector<int> v; 
	 while(op!=-1){
	    
	 	if(count!=k){
	 		
	 		v.push_back(op);
	 		count++;
			 op=Node[op].next;
		 }
		else{
		    s.push(v);
		    v.clear();
			count=0;
		}
		
	 }
     if(count!=0) s.push(v);//当时做的时候这道题我记得这里加上但是第一题却忘了,汗
     temp=s;
     int cnt=0;
     temp.pop();
     while(!temp.empty()){
     	vector<int> v=temp.top();
     	temp.pop();
     	nextnode[cnt++]=v[0];
	 }
	 nextnode[cnt]=-1;
	 int cal=0;
	 while(!s.empty()){
	 	vector<int> v=s.top();
	 	s.pop();
	 	for(int j=0;j<v.size();j++){
	 		int address=v[j];
	 		if(j!=v.size()-1)
	 		printf("%05d %d %05d\n",address,Node[address].data,Node[address].next);
	 		else if(cal!=cnt)
	 		printf("%05d %d %05d\n",address,Node[address].data,nextnode[cal++]);
	 		else if(cal==cnt)
	 		printf("%05d %d %d\n",address,Node[address].data,nextnode[cal++]);
		 }
	 }
}

做了这么多链表的题,我算是总结出了一个经验,那就是尽量不要暴力去做,尽量不要直接对链表进行一些操作,而是试图通过数组排序的方法来做!(当然题目特殊的话还是要手动模拟)。

我的做法就是,题目让我们将链表按照“块”来逆转,但是块内顺序不变,那这就好做了,我们遍历一遍数组,然后将每个块的节点地址都保存下来,因为是逆转,所以我们可以用stack里面内嵌vector来存储,然后出栈就是逆序的!到这里我们已经解决了80%的问题了,还需要解决最后一个问题——next,这样直接输出的话块与块之间的next值对不上,所以我们可以提前遍历一遍stack,存储从第二个块开始每个块第一个节点的地址(最后一个手动赋值为-1),输出的时候判断一下即可,具体可以看我代码。

你可能感兴趣的:(PTA,c++,pat,算法,数据结构,开发语言)