统计 K-Free 子集的总数
难度:
标签:
题目描述
代码结果
运行时间: 46 ms, 内存: 16.1 MB
/*
* 思路:
* 1. 创建一个函数用于判断一个子集是否为K-Free。
* 2. 使用流生成所有可能的子集并过滤掉不满足条件的子集。
* 3. 对过滤后的子集计数。
*/
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
public long countKFreeSubsets(int[] nums, int k) {
List<List<Integer>> subsets = IntStream.range(0, 1 << nums.length)
.mapToObj(i -> IntStream.range(0, nums.length)
.filter(j -> (i & (1 << j)) != 0)
.mapToObj(j -> nums[j])
.collect(Collectors.toList()))
.collect(Collectors.toList());
return subsets.stream()
.filter(subset -> isKFree(subset, k))
.count();
}
private boolean isKFree(List<Integer> subset, int k) {
for (int i = 0; i < subset.size(); i++) {
for (int j = i + 1; j < subset.size(); j++) {
if (Math.abs(subset.get(i) - subset.get(j)) == k) {
return false;
}
}
}
return true;
}
}
解释
方法:
题解的思路是将数组中的数字根据它们除以k的余数进行分类,存储在字典中,其中键是余数,值是具有相同余数的数字列表。对于每个余数类别,使用动态规划计算可能的子集数量。动态规划数组dp记录了当前长度的子序列可以形成的'k-free'子集数量。如果两个相邻数字之差等于k,则该子集可以选择包含或不包含前一个数字,否则可以自由选择包含任何前面的数字。最后,所有余数类别的结果相乘得到最终答案。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
题解中提到将数组进行排序,排序后的数组是如何帮助进行余数分类和后续的动态规划计算的?
▷🦆
在动态规划的过程中,为什么当两个相邻数字之差等于k时,状态转移方程会变化?这样的变化是基于什么样的逻辑或假设?
▷🦆
题解中提到的动态规划数组dp的每个元素dp[j]代表的是什么具体含义?如何解释dp数组中每个值的计算过程?
▷