让所有学生保持开心的分组方法数
难度:
标签:
题目描述
You are given a 0-indexed integer array nums
of length n
where n
is the total number of students in the class. The class teacher tries to select a group of students so that all the students remain happy.
The ith
student will become happy if one of these two conditions is met:
- The student is selected and the total number of selected students is strictly greater than
nums[i]
. - The student is not selected and the total number of selected students is strictly less than
nums[i]
.
Return the number of ways to select a group of students so that everyone remains happy.
Example 1:
Input: nums = [1,1] Output: 2 Explanation: The two possible ways are: The class teacher selects no student. The class teacher selects both students to form the group. If the class teacher selects just one student to form a group then the both students will not be happy. Therefore, there are only two possible ways.
Example 2:
Input: nums = [6,0,3,3,6,7,2,7] Output: 3 Explanation: The three possible ways are: The class teacher selects the student with index = 1 to form the group. The class teacher selects the students with index = 1, 2, 3, 6 to form the group. The class teacher selects all the students to form the group.
Constraints:
1 <= nums.length <= 105
0 <= nums[i] < nums.length
代码结果
运行时间: 77 ms, 内存: 25.6 MB
/*
* 思路:
* 1. 首先将数组 nums 进行排序。
* 2. 使用 Java Stream 对数组进行处理。
* 3. 计算有多少学生会保持开心,分为两种情况:
* a. 学生被选中且选中的学生人数大于 nums[i]。
* b. 学生未被选中且选中的学生人数小于 nums[i]。
* 4. 遍历排序后的数组,统计满足条件的学生人数,并根据这些人数计算出满足所有学生开心的分组方法数。
*/
import java.util.Arrays;
public class Solution {
public long countHappyGroups(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
return Arrays.stream(nums)
.boxed()
.collect(Collectors.groupingBy(i -> i))
.entrySet()
.stream()
.mapToInt(entry -> {
int count = entry.getValue().size();
return (count == 0 || nums[count - 1] < count) && (count == n || nums[count] > count) ? 1 : 0;
})
.sum();
}
}
解释
方法:
题解首先对数组 nums 进行排序。排序后,可以利用数组的顺序属性来判断哪些选中的学生人数可以使全部学生保持开心。\n\n对于每个学生 i ,要满足的条件是:\n1. 如果这位学生被选中,那么至少要有 nums[i] + 1 个学生被选中(因为要严格大于 nums[i])。\n2. 如果这位学生没有被选中,被选中的学生数必须严格小于 nums[i]。\n\n由于数组已经排序,nums[i] 是递增的,因此可以通过遍历排序后的数组,检查每个可能的学生人数 k 是否满足所有学生的开心条件:\n- nums[0] > 0 意味着没有学生被选中时,所有学生都会开心。\n- 对于 k = i (从 1 开始),如果 nums[i-1] < i < nums[i],则选择 i 个学生会使得所有学生保持开心。\n\n最终,算法统计并返回所有可能让学生开心的组合数量。
时间复杂度:
O(n log n)
空间复杂度:
O(1)
代码细节讲解
🦆
排序数组之后,为什么可以通过遍历排序后的数组来检查每个可能的学生人数 k 是否满足所有学生的开心条件?
▷🦆
在题解中提到当`nums[0] > 0`时,会增加一种全选的方法,但是否应该是`nums[0] == 0`时增加全选的方法?
▷🦆
题解中提到`如果 nums[i - 1] < i < nums[i]`时,增加一种方法。为什么这个条件能保证选择 i 个学生会使得所有学生保持开心?
▷🦆
如果数组中有重复的元素,这种方法是否还能正确地计算出所有可能的开心的分组方法数?
▷