1075 链表元素分类 (25 point(s))

// 20 points
#include <bits/stdc++.h>
using namespace std;

struct Node{
	string Address;
	int flag;
};

int main() {
	int n, k, Data;
	string first, Address, Next;
	map<int, Node> toNode;
	map<string, string> toNext; 
	map<string, int> toData; 
	vector<int> minus, insideK, outsideK, ans;
	
	cin >> first >> n >> k;
	
	for(int i = 0;i < n; i++){
		cin >> Address >> Data >> Next;
		// 存放Address下一个地址Next 
		toNext[Address] = Next;
		toData[Address] = Data;
		
		// 判断分类
		if(Data < 0) toNode[Data] = {Address, 1};
		else if(0 <= Data && Data <= k)toNode[Data] = {Address, 2};
		else toNode[Data] = {Address, 3};
	}
	
	while(first != "-1"){
		// 获取地址的Data 判断flag分类到不同vector中 
		if(toNode[toData[first]].flag == 1) minus.push_back(toData[first]);
		if(toNode[toData[first]].flag == 2) insideK.push_back(toData[first]);
		if(toNode[toData[first]].flag == 3) outsideK.push_back(toData[first]);
		
		first = toNext[first]; 
	}
	
	for(auto m: minus) ans.push_back(m);
	for(auto i: insideK) ans.push_back(i);
	for(auto o: outsideK) ans.push_back(o);
	
	int i;
	for(i = 0; i < ans.size() - 1; i++)
		cout << toNode[ans[i]].Address << " " << ans[i] << " " << toNode[ans[i+1]].Address << endl;
	cout << toNode[ans[i]].Address << " " << ans[i] << " " << -1 << endl;
}
//  AC
#include <bits/stdc++.h>
using namespace std;

struct Node{
	int Data, Next;
}List[100001];

int main() {
	int n, k, Data, start, Address, Next;
	vector<int> v[3];
	cin >> start >> n >> k;
	
	for(int i = 0;i < n; i++){
		scanf("%d %d %d", &Address, &Data, &Next);
		List[Address] = {Data, Next};
	}
	
	while(start != -1){
		if(List[start].Data < 0) v[0].push_back(start);
		if(0 <= List[start].Data && List[start].Data <= k) v[1].push_back(start);
		if(k < List[start].Data) v[2].push_back(start);
		
		start = List[start].Next; 
	}
	
	int i, first = 0;
	for(i = 0; i < 3; i++)
		for(int j = 0; j < v[i].size(); j++)
			if(first++ == 0)
				printf("%05d %d ", v[i][j], List[v[i][j]].Data);
			else
				printf("%05d\n%05d %d ", v[i][j], v[i][j], List[v[i][j]].Data);
	
	printf("-1\n");
}

下面用 Data 索引 Address 和 Next 的方式是不可取的,因为 Data 可能是重复的,可能有多个 1 但对应不同地址,而用同一个值来映射不同的输出,显然是做不到的。所以只能反过来,用多个不同的地址来映射 Data 。

输出的时候参考的代码用了以前没有见过的方式,因为是三行 vector 一起输出,所以不能够像以前一行向量直接读取下一个向量元素。

不过可以看到,一个结点的下一个结点地址就是下一个结点的地址。所以只需要当前结点不输出下一个结点的地址,而下一个结点多输出一次本结点的地址,分别当作上一个结点的下一结点地址与当前结点的地址即可。

if(first++ == 0)
	printf("%05d %d ", v[i][j], List[v[i][j]].Data);
else
	printf("%05d\n%05d %d ", v[i][j], v[i][j], List[v[i][j]].Data);

输出的时候因为地址的数据是 int 但是需要高位补零所以用了 %05d 这个跟 cout 的 setw() 和 setfill() 作用类似。

参考代码


(不可取思路)

PAT (Basic Level) 1025 反转链表 (25 point(s))

借鉴了之前这题的解法,只不过当时是根据位置改变位置,此题是根据数据 Data 来排序,所以需要把原本解法的地址对数据索引改为数据向地址索引。

但是写完后超时了,当时考虑就避免了二重循环了,因为数据集规模是 10^5 ,多次循环可能有超时可能。但是没想到常数规模的还是超时了。

虽然上面说这里的思路不可取,但是用 map 来索引和分类的思路是没有什么问题的。只不过用来索引的对象搞错了。


这题取 cin cout 可能会超时,得改成 scanf 和 printf 。PAT用下面这个东西日常没有卵用。

ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

sync_with_stdio和cin.tie(0); cout.tie(0);

但是按照错误思路的话,虽然修好了 cin cout 超时的问题,但不能避免由于重复的 Data 导致地址被覆盖,还是卡测试点五。得用地址 Address 来索引前提变量。

以后用 map 或 set 的时候得考虑数据的 key 是否有重复。

当时也有考虑用 unordered_multimap 但该容器重复的 key 是按照填入顺序来排序的,而要实际顺序还是得按照前后地址的索引来遍历,跟填入的顺序没有关系。

当然也可以先用一个散列数组放入数据,再根据顺序放入 unordered_multimap 。但如果都用这么大的散列了,还不如直接用散列数组。

测试点五

上一篇:PAT乙级1075链表元素分类 25(分)


下一篇:1075 - Incorrect table definition there can be only one auto