树状数组上二分:
按身高从低到高考虑,当前要安排的人为x,因为x之前的人都已经在队列中排好了,所以x是待排的人中身高最小的,我们要在队列中找到没有安排人且序号最小的位置把x放入。
因为所有人的身高会存在相同的,所以我们对于{h,k}定义的排序规则为:
如果h相同,则按k降序排列;否则按h升序排列。
解决的思路:
对people排序好后,由前往后处理第i个人{h,k},因为在第i个人之前有k个人比他高,而第i个人的身高已经是目前未入队的人里面最低的了,所以我们要在树状数组中二分查找找到前缀和为k+1的位置,把它放入。然后删去这个位置,更新树状数组即可。
class Solution {
public:
int tr[2010];
int n;
int lowbit(int x){
return x&-x;
}
void add(int u,int k){
for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=k;
}
int query(int u){
int res=0;
for(int i=u;i;i-=lowbit(i)) res+=tr[i];
return res;
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
n=people.size();
vector<vector<int>> ans(n);
sort(people.begin(),people.end(),[](vector<int> a,vector<int> b){
if(a[0]==b[0]) return a[1]>b[1];
else return a[0]<b[0];
});
for(int i=1;i<=n;i++) add(i,1);
for(auto p:people){
int rk=p[1]+1;
int l=1,r=n;
while(l<r){
int m=(l+r)>>1;
if(query(m)<rk) l=m+1;
else r=m;
}
ans[r-1]=p;
add(r,-1);
}
return ans;
}
};
时间复杂度:
空间复杂度: