题目:让所有学生保持开心的分组方法数
给你一个下标从 0 开始、长度为 n 的整数数组 nums ,其中 n 是班级中学生的总数。班主任希望能够在让所有学生保持开心的情况下选出一组学生:
如果能够满足下述两个条件之一,则认为第 i 位学生将会保持开心:
- 这位学生被选中,并且被选中的学生人数 严格大于
nums[i]。 - 这位学生没有被选中,并且被选中的学生人数 严格小于
nums[i]。
返回能够满足让所有学生保持开心的分组方法的数目。
示例 1:
输入: nums = [1,1]
输出: 2
解释:
有两种可行的方法:
班主任没有选中学生。
班主任选中所有学生形成一组。
如果班主任仅选中一个学生来完成分组,那么两个学生都无法保持开心。因此,仅存在两种可行的方法。
示例 2:
输入: nums = [6,0,3,3,6,7,2,7]
输出: 3
解释:
存在三种可行的方法:
班主任选中下标为 1 的学生形成一组。
班主任选中下标为 1、2、3、6 的学生形成一组。
班主任选中所有学生形成一组。
提示:
1 <= nums.length <= 1050 <= nums[i] < nums.length
解析
让所有学生都开心了,感觉我们做题的人不是很开心啊(doge)
需要找到所有子数组的组合方式,使得选中的子数组里每一个数字都小于子数组的长度,没有被选中的数字都大于子数组的长度。暴力求解必然会超时。
根据第二个示例发现,选中下标为1/2/3/6的学生的时候,数字刚好是nums里偏小的这一部分,提供了思路,可以先把nums排序一次,这样重排之后的下标+1这个值(因为下标是从0开始)就表示选中了哪些人。而只要下标对应的num数字 小于 下标+1 小于num后边的那个数字,就是符合条件的一个解。
代码
class Solution:
def countWays(self, nums: List[int]) -> int:
count = 0
nums = sorted(nums)
for index, v in enumerate(nums):
if index < len(nums) - 1:
if index + 1 > v and index + 1 < nums[index+1]:
count += 1
else:
if index + 1 > v and index + 1:
count += 1
if nums[0] > 0:
count += 1
return count
这里代码写得清晰明了一些,也可以使用itertools.pairwise来简化一下。