题目地址:
https://www.acwing.com/problem/content/description/115/
有
N
N
N个元素,编号
1
,
2..
N
1,2..N
1,2..N,每一对元素之间的大小关系是确定的,关系具有反对称性,但不具有传递性。注意:不存在两个元素大小相等的情况。也就是说,元素的大小关系是
N
N
N个点与
N
×
(
N
−
1
)
2
\frac{N×(N−1)}{2}
2N×(N−1)条有向边构成的任意有向图。然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过
10000
10000
10000次提问来获取信息,每次提问只能了解某两个元素之间的关系。现在请你把这
N
N
N个元素排成一行,使得每个元素都小于右边与它相邻的元素。你可以通过我们预设的bool函数compare
来获得两个元素之间的大小关系。例如,编号为
a
a
a和
b
b
b的两个元素,如果元素
a
a
a小于元素
b
b
b,则compare(a,b)
返回true
,否则返回false
。将
N
N
N个元素排好序后,把他们的编号以数组的形式输出,如果答案不唯一,则输出任意一个均可。
数据范围:
1
≤
N
≤
1000
1≤N≤1000
1≤N≤1000
可以直接归并排序。归并排序的比较次数是小于 N log 2 N N\log_2N Nlog2N的。代码如下:
// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.
#include <vector>
using namespace std;
class Solution {
public:
vector<int> specialSort(int N) {
vector<int> v;
for (int i = 1; i <= N; i++) v.push_back(i);
merge_sort(v, 0, v.size() - 1);
return v;
}
void merge_sort(vector<int>& v, int l, int r) {
if (l >= r) return;
static vector<int> tmp(v.size());
int mid = l + r >> 1;
merge_sort(v, l, mid);
merge_sort(v, mid + 1, r);
int i = l, j = mid + 1, idx = i;
while (i <= mid && j <= r)
if (compare(v[i], v[j]))
tmp[idx++] = v[i++];
else
tmp[idx++] = v[j++];
while (i <= mid) tmp[idx++] = v[i++];
while (j <= r) tmp[idx++] = v[j++];
for (int i = l; i <= r; i++) v[i] = tmp[i];
}
};
时间复杂度 O ( N log N ) O(N\log N) O(NlogN),空间 O ( N ) O(N) O(N)。