{x}
blog image

Maximum AND Sum of Array

You are given an integer array nums of length n and an integer numSlots such that 2 * numSlots >= n. There are numSlots slots numbered from 1 to numSlots.

You have to place all n integers into the slots such that each slot contains at most two numbers. The AND sum of a given placement is the sum of the bitwise AND of every number with its respective slot number.

  • For example, the AND sum of placing the numbers [1, 3] into slot 1 and [4, 6] into slot 2 is equal to (1 AND 1) + (3 AND 1) + (4 AND 2) + (6 AND 2) = 1 + 1 + 0 + 2 = 4.

Return the maximum possible AND sum of nums given numSlots slots.

 

Example 1:

Input: nums = [1,2,3,4,5,6], numSlots = 3
Output: 9
Explanation: One possible placement is [1, 4] into slot 1, [2, 6] into slot 2, and [3, 5] into slot 3. 
This gives the maximum AND sum of (1 AND 1) + (4 AND 1) + (2 AND 2) + (6 AND 2) + (3 AND 3) + (5 AND 3) = 1 + 0 + 2 + 2 + 3 + 1 = 9.

Example 2:

Input: nums = [1,3,10,4,7,1], numSlots = 9
Output: 24
Explanation: One possible placement is [1, 1] into slot 1, [3] into slot 3, [4] into slot 4, [7] into slot 7, and [10] into slot 9.
This gives the maximum AND sum of (1 AND 1) + (1 AND 1) + (3 AND 3) + (4 AND 4) + (7 AND 7) + (10 AND 9) = 1 + 1 + 3 + 4 + 7 + 8 = 24.
Note that slots 2, 5, 6, and 8 are empty which is permitted.

 

Constraints:

  • n == nums.length
  • 1 <= numSlots <= 9
  • 1 <= n <= 2 * numSlots
  • 1 <= nums[i] <= 15

Solution Explanation for Maximum AND Sum of Array

This problem asks to find the maximum possible AND sum when placing numbers from the input array nums into slots numbered from 1 to numSlots, with each slot containing at most two numbers. The AND sum is calculated by summing the bitwise AND of each number with its assigned slot number. A dynamic programming approach with bit manipulation is efficient for this.

Approach

The solution uses dynamic programming to explore all possible placements of numbers into slots. We represent the placement using a bitmask. Each bit in the bitmask corresponds to a potential placement of a number in a slot. If the bit is set, it means a number is placed in the corresponding slot. Since each slot can hold at most two numbers, we use a bitmask of size 2 * numSlots.

The state of the dynamic programming is defined by:

  • dp[mask]: The maximum AND sum achievable by placing numbers according to the bitmask mask.

The transition between states involves iterating through the available numbers and slots. For each number and each available slot, we calculate the AND sum and update dp[mask] if a better sum is found.

Time Complexity Analysis

The time complexity is dominated by the nested loops iterating through the bitmasks and the numbers. The outer loop iterates through 2^(2 * numSlots) possible bitmasks. The inner loop iterates through at most 2 * numSlots bits. The number of numbers n is at most 2 * numSlots. Therefore, the total time complexity is approximately O(n * 2^(2 * numSlots)). Since numSlots is capped at 9, this remains computationally feasible.

Space Complexity Analysis

The space complexity is O(2^(2 * numSlots)) because we need to store the dp array to hold the maximum AND sum for each bitmask. Again, the constant factor makes it manageable within the constraints.

Code Explanation (Python as Example)

The Python code implements this approach:

class Solution:
    def maximumANDSum(self, nums: List[int], numSlots: int) -> int:
        n = len(nums)
        m = numSlots << 1  # m = 2 * numSlots
        f = [0] * (1 << m)  # dp array initialized with zeros
 
        for i in range(1 << m):  # Iterate through all possible bitmasks
            cnt = i.bit_count()  # Number of bits set in the mask (numbers placed)
            if cnt > n:  # If more numbers placed than available, skip
                continue
            for j in range(m):  # Iterate through potential slots
                if i >> j & 1:  # Check if a number is placed in slot j
                    f[i] = max(f[i], f[i ^ (1 << j)] + (nums[cnt - 1] & (j // 2 + 1)))
                    # Update dp[i] using the AND sum of the current number with its slot and the previous state
        return max(f)  # Return the maximum AND sum found
 

The other languages (Java, C++, Go, TypeScript) follow a similar logic, adapting the syntax and data structures accordingly. The core dynamic programming and bit manipulation strategy remains consistent across all implementations.