LeetCode 6065. 按位与结果大于零的最长组合(位运算)

164 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目描述

方法一: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);

    }
}
  • 时间复杂度:O(2n)O(2^n)。一共 2n2^n 个状态
  • 空间复杂度:O(1)O(1)

也可以采用二进制枚举的方式进行暴力求解:

    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;
    }
  • 时间复杂度:O(n×2n)O(n \times 2^n)。一共 2n2^n 个状态,每种状态需要 O(n)O(n) 的时间来计算按位与
  • 空间复杂度:O(1)O(1)

方法二:脑筋急转弯

两个数做与运算,只有当它们存在共同的二进制位都是 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;
    }
}
  • 时间复杂度:O(C×n)O(C \times n)C=32C = 32
  • 空间复杂度: O(C)O(C)