PTA 11-散列4 Hard Version (30分)
题目地址
https://pta.patest.cn/pta/test/16/exam/4/question/680
5-18 Hashing - Hard Version (30分)
Given a hash table of size NN, 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 NN (\le 1000≤1000), which is the size of the hash table. The next line contains NN 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
根据hash表算原始的插入顺序,很有意思的题,mooc讲了思路。
/* 评测结果 时间 结果 得分 题目 编译器 用时(ms) 内存(MB) 用户 2017-07-08 11:46 答案正确 30 5-18 gcc 6 4 测试点结果 测试点 结果 得分/满分 用时(ms) 内存(MB) 测试点1 答案正确 18/18 2 1 测试点2 答案正确 4/4 2 1 测试点3 答案正确 2/2 2 1 测试点4 答案正确 2/2 2 1 测试点5 答案正确 4/4 6 4 刚开始找应该输出的点时,暴力扫描取最小,结果发现第三个点超时 后来改用堆找最小结点 发现还是超时。。。 然后没辙了,找了个带注释的测试点截图,第三个点写到,有非-1的空位 WTF! 改了之后发现这个数据量,用暴力扫最小结点耗时也是十几毫秒,没慢多少,但是按理说还是用堆比较科学。 ———————————————— 读入hash表-> 表里i位置上的元素,如果算完hash应该插在j位置上,那么从i-1,一直减到j,这些元素都要在i之前插入。 用(i-1+N)%N解决hash表的循环问题 把依赖关系计算完后,此时问题就成了拓扑排序。 再接下来就是怎么找入度为0的结点中,包含元素最小的点了。 此解法建了堆,最开始把入度为0的全部提前压进去,然后开始循环往外取。 取出后断开该结点发出的边与其它点的连接。如果断开后发现其它结点入度变成了0,那么立即把该入度为0的点扔到堆里。 */ #include<stdio.h> #define TRUE 1 #define FALSE 0 #define MAXN 1000 #define EMPTY -1 #define INFINITY 6666666 struct HashNode { int value; int visited; //是否访问过 int noCollision; //是否有冲突,建矩阵的时候用 int indegree; //入度 } gHashTable[MAXN]; int gMatrix[MAXN][MAXN]; int Heap[MAXN+1]; //堆 int HeapLength=0; //堆长 void DBG_printHeap() //debug时打印堆的 { int i; for(i=1;i<=HeapLength;i++) { printf("%d ",gHashTable[Heap[i]].value); } printf("+++++\n"); } void InsertIntoHeap(int a) //插入堆 { int i; Heap[++HeapLength]=a; i=HeapLength; while(i/2>0) { if(gHashTable[Heap[i/2]].value>gHashTable[a].value) { Heap[i]=Heap[i/2]; i=i/2; } else break; } Heap[i]=a; // DBG_printHeap(); } int DeHeap() //弹出堆顶 { if(HeapLength==0) return EMPTY; int top=Heap[1]; int temp,parent,child; Heap[1]=Heap[HeapLength--]; temp=Heap[1]; for(parent=1;2*parent<=HeapLength;parent=child) { child=parent*2; if(child!=HeapLength) { if(gHashTable[Heap[child]].value>gHashTable[Heap[child+1]].value) child++; } if(gHashTable[temp].value>gHashTable[Heap[child]].value) Heap[parent]=Heap[child]; else break; } Heap[parent]=temp; // DBG_printHeap(); return top; } void CalcMatrix(int N) //计算依赖关系的邻接矩阵 { int i,idx,p; for(i=0;i<N;i++) { if(gHashTable[i].noCollision==1 || gHashTable[i].value==EMPTY) continue; idx=gHashTable[i].value%N; p=(i-1+N)%N; while(p!=idx) { if(gHashTable[p].value!=EMPTY) gMatrix[p][i]=TRUE; gHashTable[i].indegree++; p=(p-1+N)%N; } gMatrix[idx][i]=TRUE; gHashTable[i].indegree++; } } void DeleteEdges(int idx,int N) //删边 { int i; for(i=0;i<N;i++) { if(gMatrix[idx][i]) { // gMatrix[idx][i]=FALSE; gHashTable[i].indegree--; if(gHashTable[i].indegree==0) { // gHashTable[i].visited=TRUE; InsertIntoHeap(i); } } } // gHashTable[idx].visited=TRUE; } int InitHeapBeforePop(int N) //最开始时扫描结点,把入度为零的扔堆里面 { int i; for(i=0;i<N;i++) { if(gHashTable[i].visited==TRUE || gHashTable[i].indegree!=0) continue; else InsertIntoHeap(i); } } int main() { int N,i,temp,firstprint; scanf("%d",&N); for(i=0;i<N;i++) { scanf("%d",&gHashTable[i].value); if(gHashTable[i].value%N==i) gHashTable[i].noCollision=TRUE;// 下标和hash值相符,说明没冲突 if(gHashTable[i].value<0) gHashTable[i].value=EMPTY; //标识空位 if(gHashTable[i].value==EMPTY) gHashTable[i].visited=TRUE; //把空位的visited置1,后续不处理 } CalcMatrix(N); InitHeapBeforePop(N); firstprint=1; //处理格式问题,第一个字符前面不加空格 while((temp=DeHeap()) != EMPTY) { DeleteEdges(temp,N); if(!firstprint) putchar(' '); printf("%d",gHashTable[temp].value); firstprint=0; } }
posted on 2017-07-09 12:48 gravitykey 阅读(698) 评论(0) 编辑 收藏 举报