Facebook Pixel

2275. Largest Combination With Bitwise AND Greater Than Zero

MediumBit ManipulationArrayHash TableCounting
Leetcode Link

Problem Description

You are given an array of positive integers called candidates. Your task is to find the size of the largest possible combination of elements from this array such that their bitwise AND is greater than 0.

The bitwise AND operation takes multiple numbers and performs an AND operation on each bit position across all numbers. For a combination to have a bitwise AND greater than 0, at least one bit position must have a 1 in all selected numbers.

For example:

  • If candidates = [1, 5, 3], the bitwise AND would be 1 & 5 & 3 = 1 (in binary: 001 & 101 & 011 = 001)
  • If candidates = [7], the bitwise AND is simply 7

The key insight is that for the bitwise AND of a combination to be greater than 0, there must be at least one bit position where all numbers in that combination have a 1. The solution counts how many numbers have a 1 at each bit position and returns the maximum count across all bit positions.

The approach iterates through each bit position (from 0 to the bit length of the maximum number) and counts how many numbers have a 1 at that position using x >> i & 1. This gives us the maximum possible combination size where all numbers share at least one common bit set to 1.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To understand why this solution works, let's think about what makes a bitwise AND result greater than 0. When we perform AND operation on multiple numbers, the result is 0 only when there's no bit position where all numbers have a 1. Conversely, for the AND to be greater than 0, there must exist at least one bit position where every number in our combination has a 1.

Consider this: if we want the largest combination with AND > 0, we need to find the bit position that has the most 1s across all candidates. Why? Because at any given bit position, we can only include numbers that have a 1 at that position in our combination. If a number has a 0 at that bit position, including it would make that bit 0 in the final AND result.

For example, if we're looking at bit position 2 and we have numbers [5, 6, 7, 4] (in binary: [101, 110, 111, 100]), only numbers 5, 6, and 7 have a 1 at position 2. So the maximum combination for this bit position is 3.

The brilliant insight is that we don't need to generate all possible combinations and check their AND results. Instead, we can independently check each bit position and count how many numbers could potentially be in a combination for that bit. The maximum count across all bit positions gives us our answer.

This works because having multiple 1s at different bit positions doesn't help us include more numbers - we're constrained by the bit position with the fewest 1s among our chosen numbers. So we optimize by finding the single bit position that allows us to include the most numbers.

Solution Approach

The implementation uses bit manipulation to efficiently solve this problem. Here's how the solution works step by step:

  1. Find the maximum bit length: First, we need to determine how many bit positions to check. We use max(candidates).bit_length() to find the number of bits needed to represent the largest number in the array. This ensures we check all relevant bit positions.

  2. Iterate through each bit position: We loop through each bit position from 0 to the maximum bit length. For each position i, we want to count how many numbers have a 1 at that position.

  3. Count 1s at each bit position: For each bit position i, we use the expression x >> i & 1 for every number x in candidates:

    • x >> i shifts the number right by i positions, bringing the bit at position i to the least significant position
    • & 1 masks everything except the least significant bit, giving us either 0 or 1
    • sum(x >> i & 1 for x in candidates) counts the total number of 1s at position i across all candidates
  4. Track the maximum count: We maintain ans to store the maximum count found so far. After checking each bit position, we update ans using max(ans, current_count).

  5. Return the result: The final value of ans represents the size of the largest combination where all numbers share at least one common bit set to 1.

For example, if candidates = [16, 17, 71, 62, 12, 24, 14]:

  • Bit position 0: numbers with 1 at this position: [17, 71] → count = 2
  • Bit position 1: numbers with 1 at this position: [71, 62, 14] → count = 3
  • Bit position 2: numbers with 1 at this position: [71, 62, 12, 14] → count = 4
  • Bit position 3: numbers with 1 at this position: [24, 62, 12, 14] → count = 4
  • Bit position 4: numbers with 1 at this position: [16, 17, 24] → count = 3

The maximum count is 4, which is our answer.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example with candidates = [5, 3, 6] to illustrate the solution approach.

First, let's convert these numbers to binary:

  • 5 = 101
  • 3 = 011
  • 6 = 110

Step 1: Find maximum bit length The maximum number is 6, which requires 3 bits to represent (110 in binary). So we'll check bit positions 0, 1, and 2.

Step 2: Check each bit position

Bit position 0 (rightmost bit):

  • 5 (101): bit at position 0 = 1
  • 3 (011): bit at position 0 = 1
  • 6 (110): bit at position 0 = 0 Count of 1s = 2 (numbers 5 and 3)

Bit position 1 (middle bit):

  • 5 (101): bit at position 1 = 0
  • 3 (011): bit at position 1 = 1
  • 6 (110): bit at position 1 = 1 Count of 1s = 2 (numbers 3 and 6)

Bit position 2 (leftmost bit):

  • 5 (101): bit at position 2 = 1
  • 3 (011): bit at position 2 = 0
  • 6 (110): bit at position 2 = 1 Count of 1s = 2 (numbers 5 and 6)

Step 3: Find maximum count The maximum count across all bit positions is 2.

Verification:

  • At bit position 0, we can combine {5, 3}: 5 & 3 = 101 & 011 = 001 = 1 (> 0) ✓
  • At bit position 1, we can combine {3, 6}: 3 & 6 = 011 & 110 = 010 = 2 (> 0) ✓
  • At bit position 2, we can combine {5, 6}: 5 & 6 = 101 & 110 = 100 = 4 (> 0) ✓

Each bit position allows us to select 2 numbers maximum, and their AND is always greater than 0 because they all share a 1 at that specific bit position. The answer is 2.

Solution Implementation

1class Solution:
2    def largestCombination(self, candidates: List[int]) -> int:
3        """
4        Find the largest combination of elements where bitwise AND is greater than 0.
5      
6        The key insight is that for AND to be > 0, at least one bit position must be 1 
7        in all selected numbers. So we count how many numbers have 1 at each bit position.
8      
9        Args:
10            candidates: List of positive integers
11          
12        Returns:
13            The size of the largest combination with bitwise AND > 0
14        """
15        # Initialize the maximum combination size
16        max_combination_size = 0
17      
18        # Find the number of bits needed to represent the largest number
19        max_value = max(candidates)
20        num_bits = max_value.bit_length()
21      
22        # Check each bit position from 0 to the highest bit
23        for bit_position in range(num_bits):
24            # Count how many numbers have 1 at the current bit position
25            count_with_bit_set = 0
26            for number in candidates:
27                # Right shift by bit_position and check if the least significant bit is 1
28                if (number >> bit_position) & 1:
29                    count_with_bit_set += 1
30          
31            # Update the maximum combination size
32            max_combination_size = max(max_combination_size, count_with_bit_set)
33      
34        return max_combination_size
35
1class Solution {
2    public int largestCombination(int[] candidates) {
3        // Find the maximum value in the candidates array
4        int maxValue = Arrays.stream(candidates).max().getAsInt();
5      
6        // Calculate the number of bits needed to represent the maximum value
7        // This determines how many bit positions we need to check
8        int numBits = Integer.SIZE - Integer.numberOfLeadingZeros(maxValue);
9      
10        // Variable to store the maximum count of numbers with same bit set
11        int maxCount = 0;
12      
13        // Check each bit position from 0 to numBits-1
14        for (int bitPosition = 0; bitPosition < numBits; bitPosition++) {
15            // Count how many numbers have the current bit position set to 1
16            int currentBitCount = 0;
17          
18            // Iterate through all candidates
19            for (int candidate : candidates) {
20                // Check if the bit at current position is set (equals 1)
21                // Right shift by bitPosition and check the least significant bit
22                currentBitCount += (candidate >> bitPosition) & 1;
23            }
24          
25            // Update the maximum count if current bit position has more numbers
26            maxCount = Math.max(maxCount, currentBitCount);
27        }
28      
29        // Return the maximum size of combination where AND is greater than 0
30        return maxCount;
31    }
32}
33
1class Solution {
2public:
3    int largestCombination(vector<int>& candidates) {
4        // Find the maximum value to determine the highest bit position we need to check
5        int maxValue = *max_element(candidates.begin(), candidates.end());
6      
7        // Calculate the number of bits needed to represent the maximum value
8        // __builtin_clz counts leading zeros in a 32-bit integer
9        // 32 - leading_zeros gives us the position of the highest set bit
10        int numBitsToCheck = 32 - __builtin_clz(maxValue);
11      
12        int maxCombinationSize = 0;
13      
14        // Check each bit position from 0 to the highest bit
15        for (int bitPosition = 0; bitPosition < numBitsToCheck; ++bitPosition) {
16            int countWithBitSet = 0;
17          
18            // Count how many numbers have the current bit position set to 1
19            for (int number : candidates) {
20                // Right shift by bitPosition and check if the least significant bit is 1
21                countWithBitSet += (number >> bitPosition) & 1;
22            }
23          
24            // The maximum combination size is the maximum count of numbers
25            // that share a common bit position set to 1
26            maxCombinationSize = max(maxCombinationSize, countWithBitSet);
27        }
28      
29        return maxCombinationSize;
30    }
31};
32
1/**
2 * Finds the size of the largest combination where the bitwise AND is greater than 0.
3 * The strategy is to count how many numbers have a 1-bit at each bit position,
4 * since the AND of those numbers at that position would be non-zero.
5 * 
6 * @param candidates - Array of positive integers to form combinations from
7 * @returns The size of the largest valid combination
8 */
9function largestCombination(candidates: number[]): number {
10    // Find the maximum value to determine the number of bits to check
11    const maxValue: number = Math.max(...candidates);
12  
13    // Calculate the number of bits in the binary representation of the maximum value
14    const bitCount: number = maxValue.toString(2).length;
15  
16    // Track the maximum count of numbers sharing a common bit
17    let maxCombinationSize: number = 0;
18  
19    // Check each bit position from 0 to bitCount-1
20    for (let bitPosition: number = 0; bitPosition < bitCount; bitPosition++) {
21        // Count how many numbers have a 1-bit at the current bit position
22        let currentBitCount: number = 0;
23      
24        for (const candidate of candidates) {
25            // Right shift by bitPosition and check if the least significant bit is 1
26            currentBitCount += (candidate >> bitPosition) & 1;
27        }
28      
29        // Update the maximum combination size if current count is larger
30        maxCombinationSize = Math.max(maxCombinationSize, currentBitCount);
31    }
32  
33    return maxCombinationSize;
34}
35

Time and Space Complexity

Time Complexity: O(n × log M)

The algorithm iterates through each bit position from 0 to max(candidates).bit_length() - 1. The number of bit positions is log M where M is the maximum value in the candidates array. For each bit position, it checks all n candidates to count how many have that bit set using sum(x >> i & 1 for x in candidates), which takes O(n) time. Therefore, the total time complexity is O(n × log M).

Space Complexity: O(1)

The algorithm only uses a constant amount of extra space. The variable ans stores the maximum count, and the loop variable i is used for iteration. The generator expression sum(x >> i & 1 for x in candidates) doesn't create any additional data structures - it processes elements one at a time. No additional arrays, lists, or data structures that scale with input size are created, resulting in constant space complexity.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrectly assuming we need to find an actual combination with maximum AND value

Many people misinterpret this problem as finding the combination that produces the maximum AND result, rather than finding the largest-sized combination where AND > 0.

Wrong approach:

# Trying to maximize the AND result instead of combination size
max_and = 0
for i in range(len(candidates)):
    for j in range(i+1, len(candidates)):
        max_and = max(max_and, candidates[i] & candidates[j])

Correct understanding: We want the maximum NUMBER of elements that can be combined with AND > 0, not the maximum AND value itself.

2. Using fixed bit width instead of dynamic calculation

Hardcoding a bit width (like 32 or 64) can be inefficient or incorrect for the given input range.

Inefficient approach:

# Always checking 32 bits even if numbers are small
for bit_position in range(32):  # Wasteful if max number is small
    count = sum((x >> bit_position) & 1 for x in candidates)

Better approach:

# Only check necessary bits based on actual data
num_bits = max(candidates).bit_length()
for bit_position in range(num_bits):
    count = sum((x >> bit_position) & 1 for x in candidates)

3. Trying to generate all possible combinations

Attempting to check all possible subsets leads to exponential time complexity O(2^n).

Time-limit-exceeding approach:

from itertools import combinations
max_size = 0
for r in range(1, len(candidates) + 1):
    for combo in combinations(candidates, r):
        and_result = combo[0]
        for num in combo[1:]:
            and_result &= num
        if and_result > 0:
            max_size = r

Efficient O(n * log(max_value)) solution: Count bits at each position as shown in the correct solution.

4. Forgetting edge cases with single elements

When the array has only one element, some implementations might fail.

Potential issue:

# May fail if candidates has only one element
if len(candidates) < 2:
    return 0  # Wrong! Single element AND with itself is the element value

Correct handling: The bit-counting approach naturally handles single elements correctly since a single positive integer always has AND > 0 with itself.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the following array represent a max heap?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More