题目描述
有N个元素,编号1.2..N,每一对元素之间的大小关系是确定的,关系具有反对称性,但不具有传递性。
注意:不存在两个元素大小相等的情况。
也就是说,元素的大小关系是N个点与N*(N-1)/2条有向边构成的任意有向图。
然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过10000次提问来获取信息,每次提问只能了解某两个元素之间的关系。现在请你把这N个元素排成一行,使得每个元素都小于右边与它相邻的元素。你可以通过我们预设的
bool函数compare来获得两个元素之间的大小关系。例如,编号为a和b的两个元素,如果元素a小于元素b,则compare(a,b)返回true,否则返回false。将N个元素排好序后,把他们的编号以数组的形式输出,如果答案不唯一,则输出任意一个均可
数据范围
1≤N≤1000
输入样例
[[0, 1, 0], [0, 0, 0], [1, 1, 0]]
输出样例
[3, 1, 2]
C++ 代码
class Solution {
public:
vector<int> specialSort(int n) {
vector<int> a;
a.push_back(1); // 起点1的编号暂时保存到0的位置
// 枚举元素的编号i, (2 <= i <= n),
// 让编号i的元素的值与[1, n]中的每一个元素的值比较大小以确定i摆放的位置
for(int i = 2; i <= n; i++) {
int l = 0, r = a.size() - 1; // l, r是a数组的下标
while(l < r) {
// 优先搜索右半边的区间,目的是让元素的移动次数越少越好
int m = l + r + 1 >> 1;
// 编号为m的元素值小于编号为i的元素值
// 编号i应该摆放在右半边区间里面的某个位置
// 所以,缩小搜索区间为[m, r],继续查找
if(compare(a[m], i)) l = m;
else r = m - 1; // 否则,缩小搜索区间为[l, m - 1]
}
// 最终得到编号i应该摆放的位置为r + 1
a.push_back(i); // 编号i暂时保存到数组的尾部
// 总长度为n - 1,剔除尾部编号i,还剩n - 2个元素。即i之前的一个元素的下标为n - 2
// 把编号i移动到下标为r的元素之后r + 1的位置。
for(int j = a.size() - 2; j > r; j--) swap(a[j], a[j + 1]);
if(compare(i, a[r])) swap(a[r], a[r + 1]); // 比较确定是否交换i与r的位置
}
return a;
}
};