给你一个正整数数组 nums
和一个整数 k
。
分区 的定义是:将数组划分成两个有序的 组 ,并满足每个元素 恰好 存在于 某一个 组中。如果分区中每个组的元素和都大于等于 k
,则认为分区是一个好分区。
返回 不同 的好分区的数目。由于答案可能很大,请返回对 10^9 + 7
取余 后的结果。
如果在两个分区中,存在某个元素 nums[i]
被分在不同的组中,则认为这两个分区不同。
示例 1:
```txt
输入:nums = [1,2,3,4], k = 4
输出:6
解释:好分区的情况是 ([1,2,3], [4]), ([1,3], [2,4]), ([1,4], [2,3]), ([2,3], [1,4]), ([2,4], [1,3]) 和 ([4], [1,2,3]) 。
```
示例 2:
```txt
输入:nums = [3,3,3], k = 4
输出:0
解释:数组中不存在好分区。
```
示例 3:
```txt
输入:nums = [6,6], k = 2
输出:2
解释:可以将 nums[0] 放入第一个分区或第二个分区中。
好分区的情况是 ([6], [6]) 和 ([6], [6]) 。
```
提示:
1 <= nums.length, k <= 1000
1 <= nums[i] <= 10^9
好分区的数目
题目
给你一个正整数数组 nums
和一个整数 k
。
分区 的定义是:将数组划分成两个有序的 组 ,并满足每个元素 恰好 存在于 某一个 组中。如果分区中每个组的元素和都大于等于 k
,则认为分区是一个好分区。
返回 不同 的好分区的数目。由于答案可能很大,请返回对 10^9 + 7
取余 后的结果。
如果在两个分区中,存在某个元素 nums[i]
被分在不同的组中,则认为这两个分区不同。
示例 1:
1 | 输入:nums = [1,2,3,4], k = 4 |
示例 2:
1 | 输入:nums = [3,3,3], k = 4 |
示例 3:
1 | 输入:nums = [6,6], k = 2 |
提示:
-
1 <= nums.length, k <= 1000
1 <= nums[i] <= 10^9
题解
方法一:
思路
对于每个数nums[i]
,我们有选与不选两种选择,对于选择的数可以放到第一个分区中,剩余的数放到第二个分区中,想到背包问题。
考虑到每个nums[i]
的数值范围很大,我们可以考虑所有不合法的分法,然后让总的$2^n$种方案减去不合法的方案数就可以得到答案。
下面考虑不合法的方案,设分好后第一个分区的总和为a,第二个分区的总和为b。
不合法的分法有三类:
- a < k 且 b < k
- a < k 且 b >= k
- a >= k 且 b < k
可以事先排除第1种情况,第1种情况没有可行的方案数。直接得到答案0
接下来可以用01背包计数
设dp[i][j]
为前i个数中选取一些后,和为j的方案数。
初始化dp[0][0] = 1
。
若不选第i个数,则有贡献dp[i-1][j]
若选第i个数,则有贡献dp[i-1][j-nums[i-1]]
因此状态转移为dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
对于第二种不合法情况有$bad = \sum \limits_{i=0}^{k-1} dp[n][i]$种,而第三种情况和第二种情况具有对称性,因此也为bad种。
所以合法的方案数为$2^n-2*bad$种。
代码
1 | class Solution { |