【ACM】PAT. A1074 Reversing Linked List【静态链表】

题目链接
题目分析

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; 
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值