题目描述
有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]
本刚学OI的蒟蒻一开始不知道交互式问题怎么写,其实int N 表示N个整数,你只需要返回一个排好序的vector(详见代码)。样例的意思:比如
[[0, 1, 0], [0, 0, 0], [1, 1, 0]]
指的是对于3个数的每组compare
compare(1,1)=0
compare(1,2)=1
compare(1,3)=0
compare(2,1)=0
compare(2,2)=0
compare(2,3)=0
compare(3,1)=1
compare(3,2)=1
compare(3,3)=0
关于思路
二分查找
首先假设vector中有排好序的一组元素:a, b, c, d, e
现在我们要在vector中插入f,如何确定f的位置?直接二分midd=c,如果f>c那么f在c,e之间,反之在a,c之间。
O(NlogN)
代码(C++)
// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.
#include <cstdio>
#include <cstring>
#include<vector>
using namespace std;
class Solution {
public:
vector<int> specialSort(int N) //N表示N个数,分别为1~N
{
vector <int> vec; //用于排序的vector
vec.push_back(1); //先插入1,后面的元素就能和1比较
for (int i = 2; i <= N; ++i)
{
int l = 0;
int r = vec.size() - 1;
while(1)
{
//二分
if(l==r)
{
if(!compare(i, vec[l]))
{
vec.insert(vec.begin() + l + 1, i);
}
else
{
vec.insert(vec.begin() + l, i);
}
break;
}
if(l+1==r)
{
if(!compare(i, vec[r]))
{
vec.insert(vec.begin() + r + 1, i);
}
else if(!compare(vec[l], i))
{
vec.insert(vec.begin() + l, i);
}
else
{
vec.insert(vec.begin() + r, i);
}
break;
}
int midd = (l + r) >> 1;
int tmp = !compare(i, vec[midd]);
if(tmp==1)
{
l = midd+1;
}
else
{
r = midd-1;
}
}
}
return vec;//返回排好序的vector
}
};
真的是初中爷吗%%%
orz
good
不错的题解!!要上去%%%