PAT 1025. 反转链表 (25)

1025. 反转链表 (25)

时间限制
300 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue

Given a constant KK and a singly linked list LL, you are supposed to reverse the links of every KK elements on LL. For example, given LL being 1→2→3→4→5→6, if K = 3K=3, then you must output 3→2→1→6→5→4; if K = 4K=4, you must output 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 NN (\le 10^5≤10 
​5 
​​ ) which is the total number of nodes, and a positive KK (\le N≤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 NN 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 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


给定一个常数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,即最后不到K个元素不反转。

输入格式:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址、结点总个数正整数N(<= 105)、以及正整数K(<=N),即要求反转的子链结点的个数。结点的地址是5位非负整数,NULL地址用-1表示。

接下来有N行,每行格式为:

Address Data Next

其中Address是结点地址,Data是该结点保存的整数数据,Next是下一结点的地址。

输出格式:

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
输出样例:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
 

这道题困恼了我一下午,从最开始的全部用数组下标表示,到后来发现用数组存储输入数据,用vector存储实际应有的数据既能内存避免开销有能减少时间,算是一个折中方案;当把数据存在了vector中后,就可以进行翻转了,这里直接用了STL:reverse(),有好用的算法为何不用呢!一切都变得很简单了对吧。

在做题过程中遇到了几个坑,在这跟大家分享一下:

1.不要全部都用数组表示,这样空间花销太大,而且也很难进行反转;

2.输入的数据节点有可能不是有效的节点,所以要重新计算链表长度(大坑,想了两三个小时才想到);

3.反转后将最后一个节点的next置于-1;


第一版代码:思路是清晰就是太啰嗦

#include<iostream>
#include<iomanip>
#include<vector>
#include<algorithm>
using namespace std;

//通过数组初始化读入链表,地址用数组下标表示
struct Node {
	int addr;
	int next;
	int data;
}node[100001];

//将所有节点按序保存在向量中
vector<Node>v1;
vector<Node>::iterator iter;



int main()
{
	int head, N, K;
	int count=0,c=0;
	int t_addr, t_data, t_next;
	Node n;
	cin >> head >> N >> K;
	if (head == -1) {
		cout << -1 << endl;
		return 0;
	}
	for (int i = 0; i<N; i++) {
		cin >> t_addr >> t_data >> t_next;
		node[t_addr].addr = t_addr;
		node[t_addr].data = t_data;
		node[t_addr].next = t_next;
	}
	n = node[head];

	int size;
	for (size = 1; n.next != -1; n = node[n.next]) {
		//将节点保存在v1中,并按照每个节点连续,
		//size记录有效节点的个数,不直接用v1.size()是因为这样调用时间花费太大
		v1.push_back(n); size++;
	}
	v1.push_back(n);
	if (K != 1) {//若K!=1则开始反转
		for (int c = 0; size >= K; c++) {//c用来记录反转的次数,便于每次设置反转的位置
			reverse(v1.begin() + c*K, v1.begin() + (c + 1)*K);
			size -= K;
		}
	}

	//调整每个节点的next地址;
	for (iter = v1.begin(); iter != v1.end(); iter++) {
		if (iter + 1 == v1.end()) {
			Node &y = *iter;
			y.next = -1;
		}else{
			Node &x = *iter;
			Node &y = *(iter + 1);
			x.next = y.addr;
		}
	}
	//输出节点
	for (iter = v1.begin(); iter != v1.end(); iter++) {
		n = *iter;
		if (iter + 1 < v1.end())
			cout << setfill('0') << setw(5) << n.addr << ' ' << n.data << ' ' << setfill('0') << setw(5) << n.next << endl;
		else {
			cout << setfill('0') << setw(5) << n.addr << ' ' << n.data<< ' '<<n.next  << endl;
			 
		}
	}
	return 0;
}

第二版代码:觉得优化的不错了,如果还有优化之处的欢迎联系评论

#include<iostream>
#include<iomanip>
#include<vector>
#include<algorithm>
using namespace std;

struct Node {
	int next;
	int data;
}node[100010];


int main()
{
	int head, N, K;
	vector<int> list;
	int t_addr, t_data, t_next;

	cin >> head >> N >> K;
	if (head == -1) {
		cout << -1 << endl;
		return 0;
	}
	for (int i = 0; i < N; i++)
	{
		cin >> t_addr >> t_data >> t_next;
		node[t_addr].data = t_data;
		node[t_addr].next = t_next;
	}
	int size = 0;
	int p = head;
	while (head != -1)
	{
		list.push_back(head);

		head = node[head].next;
	}
	size = list.size();
	int i = 0;
	while (i + K <= size)
	{
		reverse(&list[i], &list[i + K]);
		i = i + K;
	}

	for (i = 0; i < size - 1; i++)
		cout << setfill('0') << setw(5) << list[i] << ' ' << node[list[i]].data << ' ' << setfill('0') << setw(5) << list[i + 1] << endl;
	cout << setfill('0') << setw(5) << list[i] << ' ' << node[list[i]].data << ' ' << "-1" << endl;
	return 0;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值