携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情
题目描述
有 n 个人被分成数量未知的组。每个人都被标记为一个从 0 到 n - 1 的唯一ID 。
给定一个整数数组 groupSizes ,其中 groupSizes[i] 是第 i 个人所在的组的大小。例如,如果 groupSizes[1] = 3 ,则第 1 个人必须位于大小为 3 的组中。
返回一个组列表,使每个人 i 都在一个大小为 groupSizes[i] 的组中。
每个人应该 恰好只 出现在 一个组 中,并且每个人必须在一个组中。如果有多个答案,返回其中 任何 一个。可以 保证 给定输入 至少有一个 有效的解。
示例 1:
输入:groupSizes = [3,3,3,3,3,1,3] 输出:[[5],[0,1,2],[3,4,6]] 解释: 第一组是 [5],大小为 1,groupSizes[5] = 1。 第二组是 [0,1,2],大小为 3,groupSizes[0] = groupSizes[1] = groupSizes[2] = 3。 第三组是 [3,4,6],大小为 3,groupSizes[3] = groupSizes[4] = groupSizes[6] = 3。 其他可能的解决方案有 [[2,1,6],[5],[0,4,3]] 和 [[5],[0,6,2],[4,3,1]]。 示例 2:
输入:groupSizes = [2,1,3,3,3,2] 输出:[[1],[0,5],[2,3,4]]
提示:
- groupSizes.length == n
- 1 <= n <= 500
- 1 <= groupSizes[i] <= n
题目元素
- 将n个人按照给定数组进行分组,这些人的编号分别为0-(n-1);
- 给定数组为对应下边编号的人所在的数组的人员数量,也可以把给定数组的每个元素当成每个人员所在的数组数量,返回这些人员的组成关系的数组。
- 给定数组groupSizes,表示每个人所在的组大小,且每个组的成员不重复,即每个人只会出现在一个分组中,所以可以确定总共的组数,即groupSizes中重复的组数次数一定是这个组人数的倍数。
解题思路
假设groupSizes中的元素为[1,2,2,2,2,3,3,3];
则数组中的所有组数为1/1+4/2+3/3=4。所以总共有8个人,被分到到了4个组中。第一个组1个人,第二个和第三个组都是2个人,第四个组3个人;
确定了组数及对应的人数之后,就可以根据已知的成员所在的成员个数依次放进对应组中即可得到答案。
解题步骤:
第一轮循环,先初始化一个map存储组大小对应的人员,它的作用就是将所有组大小人数相同的人员放到一起,方便后续分组;
第二轮循环,循环上面初始化好的map,创建一个内部循环,循环对象为组大小对应的所有人员,然后放入分组中
代码实现
/**
*
* @param groupSizes
* @return
*/
public static List<List<Integer>> groupThePeople(int[] groupSizes) {
List<List<Integer>> list = new ArrayList<>();
// 创建每个数字对应的元素列表
HashMap<Integer, List<Integer>> timesMap = new HashMap<>();
for (int i = 0;i < groupSizes.length;i++) {
int size = groupSizes[i];
// 数组大小对应相应元素的数组数组
timesMap.putIfAbsent(size,new ArrayList<>());
// 将当前元素放入map中
timesMap.get(size).add(i);
}
// 组装数组数据
timesMap.forEach((num,items)-> {
// 数组内有元素
// 得到的是组数
int groupNum = items.size() / num;
for (int i=0;i < groupNum ; i++) {
// 从item里面取
List<Integer> eachGroup = new ArrayList<>();
for (int j =0;j < num;j++) {
// 对应item的下标
eachGroup.add(items.get(num*i+j));
}
list.add(eachGroup);
}
});
return list;
}
复杂度
- 时间复杂度:O(n),n为给定的groupSizes的长度;
- 空间复杂度,O(n),n为创建的map的长度。