本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目描述
方法一:DFS(超时)
- 采用LeetCode 78. 子集的思路,求出所有子集
- 每个子集执行 按位与 ,找出结果大于0的最长子集。
public class Solution {
int maxLen = 0;
public int largestCombination(int[] candidates) {
dfs(candidates, 0, 0xFFFF, 0);
return maxLen;
}
private void dfs(int[] candidates, int idx, int res, int len) {
if (idx == candidates.length) {
if (res > 0) {
maxLen = Math.max(maxLen, len);
}
return ;
}
if (res <= 0) {
return ;
}
// 原序列中的每个数字的状态可能有两种,即「在子集中」和「不在子集中」
// 在子集中:
dfs(candidates, idx + 1, res & candidates[idx], len + 1);
// 不在子集中:
dfs(candidates, idx + 1, res, len);
}
}
- 时间复杂度:。一共 个状态
- 空间复杂度:
也可以采用二进制枚举的方式进行暴力求解:
public int largestCombination(int[] candidates) {
int n = candidates.length;
int maxLen = 0;
// 枚举所有可能的组合
for (int i = 0; i < (1 << n); i++) {
int len = 0, res = 0xFFFF;
for (int j = 0; j < n; j++) {
if (((i >> j) & 1) == 1) {
len++;
res = res & candidates[j];
}
}
if (res > 0) {
maxLen = Math.max(maxLen, len);
}
}
return maxLen;
}
- 时间复杂度:。一共 个状态,每种状态需要 的时间来计算按位与
- 空间复杂度:
方法二:脑筋急转弯
两个数做与运算,只有当它们存在共同的二进制位都是 1 时,结果才不是 0
找按位与运算结果不为0的最大长度,可以转换为有多少个数有共同的二进制位都是 1。
遍历数组,统计32位上哪一位1出现的个数最多即可,该位为1的这几个数 按位与 一定大于0且长度最长。
class Solution {
public int largestCombination(int[] candidates) {
int maxLen = 0;
int[] freq = new int[32];
for (int num : candidates) {
for (int i = 0; i < 32; i++) {
if (((num >> i) & 1) == 1) {
freq[i]++;
}
}
}
for (int i = 0; i < 32; i++) {
maxLen = Math.max(maxLen, freq[i]);
}
return maxLen;
}
}
- 时间复杂度:,
- 空间复杂度: