题目意思:
有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。
贪心思路:
1、首先确定第一个,首先第一个的 k 必定等于0,可以举反例,k = 1的不可能在第一个(这个很好理解因为k等于1说明前面有一个),所以在 k 等于0找 h 最小的为第一个。
2、设立一个标记数组,每拿一个,需要比它小或相等的数+1, 比如说我第一个拿了 [ 5, 0 ],那比5小和相等的数只有 4 和 5,那在数组中把 flagNum[4]+=1; flagNum[5]+=1;
3、遍历一遍数组,找出满足条件也就是 flagNum[ people[ i ][ 0 ] ] = people[ i ][ 1 ] 的数并且之前没有选择过,有可能有几个数都满足,那么给出一个贪心选择的策略 就是选择 h-k 最小的那个,比如例子中 [ 7, 0 ] 后面同时满足的应该有 [ 5, 2 ]和 [ 6, 1 ],h越小越在前面,k越大约在前面(也就是h-k 最小)。
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
set<int> s;
//定义是否取过的标记数组
int flag[people.size() + 5];
memset(flag, 0, sizeof(flag));
//用于记录当前每个数字前面有多少个
int flagNum[1000000];
memset(flagNum, 0, sizeof(flagNum));
//结果集
vector<vector<int >> res;
//判断下界
if(!people.size()) return res;
//第一遍先找出第一个
int tmpMin = INT_MAX, tmpIndex = 0;
vector<int > tmpFirst;
for(int i = 0; i < people.size(); i++){
if(people[i][0] < tmpMin && people[i][1] == 0){
tmpMin = people[i][0];
tmpFirst = people[i];
tmpIndex = i;
}
s.insert(people[i][0]);
}
res.push_back(tmpFirst);
for(int num: s) {
if(num <= tmpFirst[0]) flagNum[num] += 1;
}
flag[tmpIndex] = 1;
while(res.size() < people.size()){
//如果条件都符合,就找前-后越小的
int min = INT_MAX;
vector<int > flagVector;
int index;
for(int i = 0; i < people.size(); i++){
if(flag[i] == 0 && people[i][0]-people[i][1] < min && flagNum[people[i][0]] == people[i][1]){
min = people[i][0]-people[i][1];
flagVector = people[i];
index = i;
}
}
res.push_back(flagVector);
for(int num: s) {
if(num <= flagVector[0]) flagNum[num] += 1;
}
flag[index] = 1;
}
return res;
}
};