PTA 7-18 Hashing - Hard Version 一个非拓扑排序的思路
Given a hash table of size , we can define a hash function . Suppose that the linear probing is used to solve collisions, we can easily obtain the status of the hash table with a given sequence of input numbers.
However, now you are asked to solve the reversed problem: reconstruct the input sequence from the given status of the hash table. Whenever there are multiple choices, the smallest number is always taken.
Input Specification:
Each input file contains one test case. For each test case, the first line contains a positive integer (), which is the size of the hash table. The next line contains integers, separated by a space. A negative integer represents an empty cell in the hash table. It is guaranteed that all the non-negative integers are distinct in the table.
Output Specification:
For each test case, print a line that contains the input sequence, with the numbers separated by a space. Notice that there must be no extra space at the end of each line.
Sample Input:
11
33 1 13 12 34 38 27 22 32 -1 21
Sample Output:
1 13 12 21 33 34 38 27 22 32
思路:
记录一个非拓扑排序的简单思路,速度也还可以:
测试点 | 结果 | 分数 | 耗时 | 内存 |
---|---|---|---|---|
0 |
答案正确
|
18 | 4 ms | 328 KB |
1 |
答案正确
|
4 | 4 ms | 328 KB |
2 |
答案正确
|
2 | 4 ms | 332 KB |
3 |
答案正确
|
2 | 5 ms | 460 KB |
4 |
答案正确
|
4 | 14 ms | 456 KB |
简单概括说,就是用一个堆和一个队列来回倒腾。
首先,堆是按照key的值大小的小顶堆,堆内每个元素都记录3个值:到hash表的索引 index
,key值 data
,按照给定hash函数本来该值所应该放的地址 shouldBe
;
用一个bool数组模拟记录hash表各位置上的元素是否已经插入;
将所有元素推入小顶堆,依次弹出,此时是按照key值大小由小到大弹出的;
每弹出一个元素,就检查其key值是否已经可以插入,判断依据:检查index
到shouldBe
之间的所有元素是否全部已经插入;
如果一个元素还不能插入,就推入普通队列里暂时存放,直到从minheap里弹出一个可以插入的元素,将这个元素输出之后,
再把这一轮所有推入普通队列的元素,重新插回minheap,进行下一轮的搜索;
另外,为了适当加速,在检查可行性函数bool checkAvail(Elem &)
里,即使是对不可行的元素,也修改其 shouldBe
指针,从而可以一定程度减少重复检查次数。
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
constexpr int kMaxSize = 1024;
int tableSize;
struct Elem {
int index, data, shouldBe;
bool operator<(const Elem &e) const {
return data > e.data;//min heap;
}
};
bool inserted[kMaxSize]{};//by order of hashTable;
priority_queue<Elem> minHeap;
queue<Elem> que;//for temporary storing invalid elem;
bool checkAvail(Elem &elem){
//backward check whether all clear between index and shouldBe;
int idx = elem.shouldBe, stp = elem.index;
while (idx != stp){
if (inserted[idx] == false){
elem.shouldBe = idx;//next time only need to check from crt blocking cell;
return false;
}
idx = (idx + 1) % tableSize;//increment;
}
return true;
}
int main(){
ios::sync_with_stdio(false);
cin >> tableSize;
Elem tmpE;
for (int i = 0; i < tableSize; ++i){
tmpE.index = i;
cin >> tmpE.data;
if (tmpE.data < 0){//regard empty cell as a clear loc;
inserted[i] = true;
continue;
}
tmpE.shouldBe = tmpE.data % tableSize;
minHeap.push(tmpE);//O(logN);
}
bool fir = true;
while (!minHeap.empty()){
while (!minHeap.empty()){
tmpE = minHeap.top();
minHeap.pop();
//if an elem is just at its right place, output it;
if (tmpE.index == tmpE.shouldBe) break;
else if (checkAvail(tmpE)) break;//if all blocked elem is cleared;
//else : all temporarily-invalid elem are pushed into a queue;
que.push(tmpE);
}
if (fir) fir = false;
else cout << ' ';
cout << tmpE.data;
inserted[tmpE.index] = true;//regard as cleared;
//push back into min heap for next loop checking;
while (!que.empty()){
tmpE = que.front();
que.pop();
minHeap.push(tmpE);//O(logN);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话