Description
There are n
people that are split into some unknown number of groups. Each person is labeled with a unique ID from 0
to n - 1
.
You are given an integer array groupSizes
, where groupSizes[i]
is the size of the group that person i
is in. For example, if groupSizes[1] = 3
, then person 1
must be in a group of size 3
.
Return a list of groups such that each personi
is in a group of size groupSizes[i]
.
Each person should appear in exactly one group, and every person must be in a group. If there are multiple answers, return any of them. It is guaranteed that there will be at least one valid solution for the given input.
Example 1:
Input: groupSizes = [3,3,3,3,3,1,3] Output: [[5],[0,1,2],[3,4,6]] Explanation: The first group is [5]. The size is 1, and groupSizes[5] = 1. The second group is [0,1,2]. The size is 3, and groupSizes[0] = groupSizes[1] = groupSizes[2] = 3. The third group is [3,4,6]. The size is 3, and groupSizes[3] = groupSizes[4] = groupSizes[6] = 3. Other possible solutions are [[2,1,6],[5],[0,4,3]] and [[5],[0,6,2],[4,3,1]].
Example 2:
Input: groupSizes = [2,1,3,3,3,2] Output: [[1],[0,5],[2,3,4]]
Constraints:
groupSizes.length == n
1 <= n <= 500
1 <= groupSizes[i] <= n
这道题说是将n个人(编号为0到 n-1)分为若干个组,现在给了一个 groupSizes 数组,其中 groupSizes[i] 是编号为i的人所在的组的总人数,现在让返回分成的这些组,并将该组的人的编号放进去。通过分析例子不难理解题意,例子1中,一堆3中间有一个有一个1,其位置是5,那么很显然,编号为5的人,单独是一组,那么博主就想到,应该是先处理人数少的组,则可以对总人数排序,但是由于编号信息不能丢失,所以可以建立组人数和编号的 pair 对儿,然后放到一个新数组 all 中,然后对 all 进行排序,默认是以 pair 对儿中的第一个元素为 key 进行排序,即是按照组人数从小到大排序。这样就可以开始处理了,取出当前的组人数 cnt,然后新建一个数组 out,变量j从0遍历到 cnt,然后将 all[i+j][1] 加入数组 out 中,即把对应的编号加入。因为组人数是有序的,所以若当前是 cnt,则之后 cnt 个数字一定都等于 cnt,所以可以按顺序加入到 out 数组中,然后将 out 加入结果 res,此时要更新变量i,将其加上 cnt-1,因为 for 循环本身还要再加1,参见代码如下:
解法一:
class Solution { public: vector<vector<int>> groupThePeople(vector<int>& groupSizes) { vector<vector<int>> res, all; int n = groupSizes.size(); for (int i = 0; i < n; ++i) { all.push_back({groupSizes[i], i}); } sort(all.begin(), all.end()); for (int i = 0; i < n; ++i) { int cnt = all[i][0]; vector<int> out; for (int j = 0; j < cnt; ++j) { out.push_back(all[i + j][1]); } res.push_back(out); i += cnt - 1; } return res; } };
上面的方法虽然 work,但也是险过,说不定哪天就被 OJ 排除在外了,这道题其实有更简单高效的解法。并不需要排序,而是将所在群组人数相同的人归类到一起,这样可以使用一个二维数组 all,其中 all[i] 表示所在群组个数为i的人的编号的集合,大小初始化为 n+1,其中n是 groupSizes 的大小。然后i从0遍历到 n-1,将编号i放入 all[groupSizes[i]] 中,因为 groupSizes[i] 是编号为i的人所在的群组的人数,外面套个 all,就是具有相同群组人数的人的集合,若等于 groupSizes[i],说明此时的群组已经放满了,可以加入到结果 res 中,然后将其清空,以便给放之后符合条件的人,参见代码如下:
解法二:
class Solution { public: vector<vector<int>> groupThePeople(vector<int>& groupSizes) { int n = groupSizes.size(); vector<vector<int>> res, all(n + 1); for (int i = 0; i < n; ++i) { all[groupSizes[i]].push_back(i); if (all[groupSizes[i]].size() == groupSizes[i]) { res.push_back(all[groupSizes[i]]); all[groupSizes[i]].clear(); } } return res; } };
Github 同步地址:
参考资料:
https://leetcode.com/problems/group-the-people-given-the-group-size-they-belong-to/
LeetCode All in One 题目讲解汇总(持续更新中...)
喜欢请点赞,疼爱请打赏❤️~.~
微信打赏
Venmo 打赏