题目链接
题目分析
1、每 K
个元素反转一下,而非只反转前K
个(这样做有两个测试点不过)
2、含有无效结点(不再链表上)
解题思路
思路(一)
遍历链表,过程中逐块倒序保存在新申请的vector<node>
中;之后顺序输出即可(最后一组保存时正序保存)
思路(二):对结点排序,然后在数组中一块一块的倒序输出;
1、增加order
属性表示点在链表中的位置 【全部初始化为maxn
,之后没有被更新的即为无效点】
2、遍历链表,对order
属性赋值
3、根据order
对数组排序(并记录有效点的个数), 这样下标表示点在链表中的位置,st
属性表示地址
4、n/k
为一共需要反转几组,每组按数组反转输出(注意最后一个元素的特殊性)
5、最后无法凑成一组的数据单独处理,不用反转
AC程序(C++)(思路一)
/**********************************
*@ID: 3stone
*@ACM: PAT.A1074 Reversing Linked List
*@Time: 19/2/13
*@IDE: VScode 2018 + clang++
***********************************/
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 100010;
struct node {
int head, value, tail;
}list[maxn];
vector<node> S; //模拟栈(由于最后一组不翻转,用stack不方便)
vector<node> resultList;//保存最终结果
int main() {
int st, N, K, tempHead;
scanf("%d%d%d", &st, &N, &K);
for(int i = 0; i < N; i++) { //保存
scanf("%d", &tempHead);
list[tempHead].head = tempHead;
scanf("%d%d", &list[tempHead].value, &list[tempHead].tail);
}
while(st != -1) { //顺序遍历
S.clear();
for(int i = 0; i < K && st != -1; i++) { //压栈K个元素
S.push_back(list[st]);
st = list[st].tail;
}
if(S.size() == K) { //每一组倒序保存,即翻转
for(int i = K - 1; i >= 0; i--) {
resultList.push_back(S[i]);
}
} else { //最后元素无法组成一组,正序保存
for(int i = 0; i < S.size(); i++)
resultList.push_back(S[i]);
}
}
for(int i = 0; i < resultList.size() - 1; i++) {
printf("%05d %d %05d\n", resultList[i].head, resultList[i].value, resultList[i + 1].head);
}
printf("%05d %d -1\n", resultList[resultList.size() - 1].head, resultList[resultList.size() - 1].value);
system("pause");
return 0;
}
AC程序(C++)(思路二)
/**************************
*@Author: 3stone
*@ACM: PAT A1074 Reversing Linked List
*@Time: 18/7/18
*@IDE: VSCode 2018
***************************/
#include<cstdio>
#include<algorithm>
#define maxn 100010
using namespace std;
struct Node{
int st, data, ed;
int order;
}node[maxn + 5];
bool cmp(Node a, Node b){
return a.order < b.order;
}
int main(){
int n, k, head;
while(scanf("%d%d%d", &head, &n, &k) != EOF){
for(int i = 0; i < maxn; i++){//初始化
node[i].order = maxn;
}
for(int i = 0; i < n; i++){//输入数据
int ad;
scanf("%d", &ad);
node[ad].st = ad;
scanf("%d%d", &node[ad].data, &node[ad].ed);
}
//如何遍历得到order
int pre = head, num = 1, nxt = 1;
node[pre].order = 1;
while(node[pre].ed != -1){//遍历有效地址
nxt = node[pre].ed;
node[nxt].order = ++num;
pre = nxt;
}
sort(node, node + maxn, cmp);//按order排序
int group = num / k;
for(int i = 0; i < group; i++){ //数组都已经排好序了啊;直接按新序号访问即可
int j;
for(j = (i+1) * k - 1; j > i * k; j--){
printf("%05d %d %05d\n", node[j].st, node[j].data, node[j-1].st);
}
//处理每组最后一个元素
if(i != group - 1){//并非最后一组
printf("%05d %d %05d\n", node[j].st, node[j].data, node[(i+2)*k-1].st);
}
else{//最后一组 未反转部分
if(0 == num % k) {//整分,没有尾巴
printf("%05d %d -1\n", node[j].st, node[j].data);
}
else{//输出尾巴
printf("%05d %d %05d\n", node[j].st, node[j].data, node[(i+1)*k].st);
for(j = (i+1) * k; j < num -1; j++){
printf("%05d %d %05d\n", node[j].st, node[j].data, node[j].ed);
}
printf("%05d %d -1\n", node[j].st, node[j].data);
} //else
}//else
}//for - i
}//while
return 0;
}