Categories
不学无术

1074. Reversing Linked List (25) 链表反转~最后一个测试点,小心特殊情况!

原题:

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

 

分析:

初看是一道很简单的题目,对链表进行有规律的反转。我采取的方案如下:
1.读取输入,然后链表按其地址存放到map中(当然有猥琐的人可以存放到数组里用空间换时间);
2.按照链表的头指针顺着下去读取链表。建一个栈,当没有达到K个时,每个读取到的值压入栈里,然后集齐K个的时候输出。技巧是一行输出的东西可以分拆分成两块,即除第一行与最后一行特殊外,其他每两行都是:
[上一地址 ] [上个值 ] [当前地址]
[当前地址] [当前值] [下一地址]
也就是说得到当前节点后,只需要补齐上一行的”当前地址”和当前行前两项即可,等到下一个节点读入时再补上这一行的最后一个“下一地址”。
3.最后,末尾别忘了NULL指针“-1”
上面的算法复杂度是O(N)
 
但是请务必考虑下面几个特殊情况:
1. K=1, K=N
2. 给的头指针不是整条链的头指针,而是中间某个节点的。这个问题是最后一个测试点测试的东西。我一开始也试了好多无果,还好搜到了这篇文章末尾的评论部分才得到启发!另外测试点6不会考虑给的测试例有多个next指针式NULL指针(-1)的情况,有些博客中这种说法是错误的。
例如:

00000 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

这时候的正确输出是:

00000 4 99999
99999 5 68237
68237 6 -1

 


 

代码

#include <iostream>
#include <map>
#include <stack>
#include <string.h>
using namespace std;
struct Node
{
	char fake_addr[6];
	char fake_next[6];
	int data;
};
int main()
{
	char pStart[6];
	int N, K;
	cin >> pStart >> N >> K;
	map<int, Node> mapNodes;
	int multiEnd = 0;
	for (int i = 0; i < N; i++)
	{
		//Read from input
		char addr[6], next[6];
		int data;
		cin >> addr >> data >> next;
		if (strcmp(next, "-1") == 0)
			multiEnd++;
		Node node;
		node.data = data;
		strcpy(node.fake_addr, addr);
		strcpy(node.fake_next, next);
		int key = atoi(addr);
		mapNodes[key] = node;
	}
	if (true)
	{
		//奇怪的的情况,需要扫链了
		int count = 0;
		int nextPtr = atoi(pStart);
		while (nextPtr != -1)
		{
			nextPtr = atoi(mapNodes[nextPtr].fake_next);
			count++;
		}
		N = count;
	}
	stack<Node> workingStack;
	const int LIMIT = N - N % K;
	int currentFakePtr = atoi(pStart);
	bool firstLine = true;
	//能整除的范围
	for (int i = 0; i < LIMIT; i++)
	{
		if (true)
		{
			//将node压入栈准备输出
			if (currentFakePtr == -1)
			{
				break;
			}
			Node currentNode = mapNodes[currentFakePtr];
			workingStack.push(currentNode);
			currentFakePtr = atoi(currentNode.fake_next);
		}
		if (i%K == K-1)
		{
			//逐条弹栈并输出 (除最后一个节点的next地址)
			while (!workingStack.empty())
			{
				Node currentNode = workingStack.top();
				if (!firstLine)
					cout << currentNode.fake_addr << endl; //上一行的末尾
				cout << currentNode.fake_addr << " " << currentNode.data << " "; //本行的前两个元素
				workingStack.pop();
				firstLine = false;
			}
		}
	}
	//不能整除的范围,按顺序输出
	//需要考虑一开始就不能整除的情况 (LIMIT = 0)
	for (int i = LIMIT; i < N; i++)
	{
		if (currentFakePtr == -1)
		{
			break;
		}
		Node currentNode = mapNodes[currentFakePtr];
		if (!firstLine)
			cout << currentNode.fake_addr << endl; //上一行的末尾
		cout << currentNode.fake_addr << " " << currentNode.data << " "; //本行的前两个元素
		currentFakePtr = atoi(currentNode.fake_next);
		firstLine = false;
	}
	cout << "-1";
	return 0;
}

 


测试点

(这个结果还有优化的空间,不过既然已经<400ms了我就不管啦~)

测试点 结果 用时(ms) 内存(kB) 得分/满分
0 答案正确 1 360 12/12
1 答案正确 1 232 3/3
2 答案正确 1 360 2/2
3 答案正确 1 232 2/2
4 答案正确 1 232 2/2
5 答案正确 326 8424 3/3
6 答案正确 1 360 1/1

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.