本周和上周都讲了贪心算法,所以在leetcode上面挑了Greedy的算法题目来做。首先这道题目是所有贪心算法里面最简单的,是middle里面通过率最高的一道题目。
题目大意:
给定一个队列,每一个元素代表一个人,每个人有两个属性,一个是他自身的身高,另一个是排在他前面比他身高要高的人数。本题给定这样一个vector,用来盛放每个人的个人信息,然后让你按照每个人的这两个元素对这个队伍进行排序。
例子:
Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]:
算法:
首先,这道题目是贪心算法中的一道题目,采用贪心算法来想问题。我考虑到,因为要求排序,我们就要有排序的依据,一个就是按照身高h来排,另一个就是人数k来排。我们先考虑按照身高来排序。
一、先按身高排序
1、按升序排列:因为将个子矮的排到前面,所以后面还要考虑个子高的人的位置,这样做会很麻烦。
2、按降序排列:因为先将个子高的安排好了,那么安排个子矮的同学的时候,不会影响个子高同学的k值。也就是说,安排好个子高的同学之后,使之满足k值,然后就不用担心个子高的同学的k值再变化,因为个子矮的人的位置再也不会影响个子高的人的k值了。
所以说,先按降序排列,然后将个子高的同学先按k值升序排列。这样的话,个子矮的同学只需要按照k值insert进新的队列当中就可以了。因为个子矮的同学的k值固定,已经安排进队列的同学升高都比这个人要高,而且即将安排进来的人比他矮或者和他一样高但是k值比他大,所以他就可以放心的进入队列当中。只需要数到和他k值相同的同学个数,然后进入队列即可。这样,时间复杂度就是max{O(n),排序复杂度O(sort)}。
二、先按k值排序
因为按照k值排序,我们一定是先考虑前面的同学,这样的话,我们先安排好k值为0的同学。如果k指相同,我们就按照身高升序排列。
排好序之后,我们先安排k值为0的进入队列,然后再看k值为1的。我们设置一个变量count,让他遍历已经进入队列当中的同学,如果有身高大于将要进入同学的人,就加1,当count恰好比将要进入队列同学的k值大1的时候,我们就把这个同学放到使count变成k+1的那个同学前面去。这样做的复杂度就不如前面的那个好,因为进入一个同学就要遍历已经排好序的vector一遍。
因为第一种算法比较简单,我就按照第一种算法进行了实现。
代码如下:
class Solution
{
public:
static int cmp(const pair<int,int> a,const pair<int,int> b)
{
if(a.first==b.first)
{
if(a.second<b.second) return 1;
else return 0;
}
else if(a.first<b.first) return 0;
else return 1;
}
vector<pair<int, int>> reconstructQueue(vector<pair<int, int>>& people)
{
vector<pair<int,int>> result;
int n=people.size();
sort(people.begin(),people.end(),cmp);
int i=0;
while(n!=0)
{
result.insert(result.begin()+people[i].second,people[i]);
i++;
n--;
}
return result;
}
};