Code & Fun

题目是Queue Reconstruction by Height:

题目描述:

Suppose you have a random list of people standing in a queue. Each person is described by a pair of integers (h, k), where h is the height of the person and k is the number of people in front of this person who have a height greater than or equal to h. Write an algorithm to reconstruct the queue.

Note:
The number of people is less than 1,100.

Example

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)的二元组的列表,h表示person的高度,然后k是在队伍中站在它前面且高度大于等于他的人的个数。

我们要根据这些信息来重建这个队列(输入是乱的),是它符合上面的格式。

首先想到的就是先排序,不排序,肯定要一直扫描所有的person才能得到我们的想要的信息。

然后就按h的顺序来排序,当h相等时就按k排序。

按照上面的样例进行排序就得到:

1
[[4,4], [5, 0], [5, 1], [6, 1], [7, 0], [7, 1]]

我们先考虑第一个位置放什么,从头开始扫描:
[4,4]显然不是,[5, 0],因为k为0,所以显然就是它了,我们并不需要扫描到后面去,因为它是高度最小的且k0person,所以我们可以直接把它放到第一个位置上去,这样的话,现在我们考虑可以第二个位置了,有了放第一个的方法,我们就可以递归的去做,现在是找[[4,4],[5,1],[6,1],[7,0],[7,1]第一个放的位置,直接扫过去就可以得到[7,0]的位置,看起来好像是对的方法,但是我们很容易就发现,下一个我们就没法找出来了,因为没有k0person了,所以我们要不断的更新去做,比如[5, 0]移动到第一个位置需要经过[4,4],那么这时[4,4]前面就站着一个[5,0]而且比他高,所以在后面的扫描中,它的k应该就是3了,[7,0]向前移动的时候同理,[4,4], [5, 1], [6, 1]k都需要减一。

因为我们是不能直接修改peoplek的,所以我们需要一个数组来保存。

还有一点就是上面没有考虑到高度相同的情况,比如[7,0],[7,1],第二个人前面其实已经站着一个高度大于等于它的人了,其实它的k其实应该是0,而不是1,所以我们需要继续调整,因为可能会出现[7,0],[7,1],[7,2]的情况,所以在从前往后生成新的数组保存k值的时候,我们还需要向前扫描看前面有多少个高度相同的人才能计算出实际的k值,这样的时间复杂度是O(n^2),所以我们不保存k值,我们保存k前面有多少个高度大于等于它的人,这样的生成辅助数据的时间复杂度就是O(n)了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public:
vector<pair<int, int>> reconstructQueue(vector<pair<int, int>>& people) {

int size = people.size();
if (size == 0 || size == 1) return people;

sort(people.begin(), people.end(), [](const pair<int, int> &p1,const pair<int, int> &p2) {
return p1.first < p2.first || (p1.first == p2.first && p1.second < p2.second);
});

vector<int> m(size, 0);
m[0] = 0;
for(int i = 1;i < size;i++) {
if (people[i].first == people[i-1].first) {
m[i] = m[i-1] + 1;
} else m[i] = 0;
}
// like insert sort.
for(int i = 1;i < size;i++) {
auto p = people[i];
int t = m[i], j;
for(j = i-1;j >= 0 && (p.second - t) < (people[j].second - m[j]) ;j--) {
if (people[j].first <= p.first) m[j]++;
people[j+1] = people[j];
m[j+1] = m[j];
}
people[j+1] = p;
m[j+1] = t;
}

return people;
}
};

本文首发于Code & Fun