哈希表的逆向思维,我们首先计算每一个位置上的数据的余数是不是等于其位号(即hash的key)如果相等则记为0,否则记录差值。
如下:
位置(key) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
数据 | 33 | 1 | 13 | 12 | 34 | 38 | 27 | 22 | 32 | -1 | 21 |
余数 | 0 | 1 | 2 | 1 | 1 | 5 | 5 | 0 | 10 | -1 | 10 |
差值 | 0 | 0 | 0 | 2 | 3 | 0 | 1 | 7 | 9 | -1 | 0 |
每一处的差值代表这个数被往后挤了x位,只有他前面这x位全部被输出(对应hash表输入队列)才允许被输出。
这一步只需要一个遍历与一个额外的标记位即可。
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<string>
using namespace std;
struct DATA
{
int num = -1;
int firstleft = -1;
int left = -1;
};
int main()
{
int n, t, temp;
int empty = 0;
cin >> n;
vector<DATA> v(n);
for (int i = 0; i < n; i++)
{
scanf("%d", &t);
v[i].num = t;
if (t < 0)
{
v[i].left = -1;
v[i].firstleft = -1;
empty++;
}
else
{
temp = i - t % n;
if (temp < 0)
temp += n;
v[i].left = temp;
v[i].firstleft = temp;
}
}
int min, p;
for (int i = 0; i < n - 1 - empty; i++)
{
min = 10000000;
for (int j = 0; j < n; j++)
{
if (v[j].left == 0 && v[j].num < min)
{
p = j;
min = v[j].num;
}
}
printf("%d ", v[p].num);
for (int j = 0; j < n; j++)
{
t = j - p;
if (t < 0)
t += n;
if (v[j].firstleft >= t)
v[j].left--;
}
v[p].left = -1;
}
for (int j = 0; j < n; j++)
{
if (v[j].left == 0)
{
printf("%d", v[j].num);
break;
}
}
return 0;
}