Facebook Pixel

3344. Maximum Sized Array

MediumBit ManipulationBinary Search
Leetcode Link

Problem Description

You are given a positive integer s. You need to create a 3D array A with dimensions n × n × n, where each element is calculated using a specific formula.

For each element in the array, A[i][j][k] is defined as:

  • A[i][j][k] = i * (j OR k), where 0 <= i, j, k < n
  • The OR operation is the bitwise OR operation

Your task is to find the maximum possible value of n such that when you sum up all elements in the entire 3D array A, the total sum does not exceed s.

For example, if n = 2, you would have a 2×2×2 array with 8 elements total:

  • A[0][0][0] = 0 * (0 OR 0) = 0
  • A[0][0][1] = 0 * (0 OR 1) = 0
  • A[0][1][0] = 0 * (1 OR 0) = 0
  • A[0][1][1] = 0 * (1 OR 1) = 0
  • A[1][0][0] = 1 * (0 OR 0) = 0
  • A[1][0][1] = 1 * (0 OR 1) = 1
  • A[1][1][0] = 1 * (1 OR 0) = 1
  • A[1][1][1] = 1 * (1 OR 1) = 1

The sum would be 3, and if s >= 3, then n = 2 would be valid. You need to find the largest such n where the sum stays within the limit s.

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

Intuition

Let's think about how to calculate the sum efficiently. If we expand the sum of all elements in the 3D array:

Sum = Σ(i=0 to n-1) Σ(j=0 to n-1) Σ(k=0 to n-1) i * (j OR k)

We can rearrange this as: Sum = Σ(i=0 to n-1) i * Σ(j=0 to n-1) Σ(k=0 to n-1) (j OR k)

Notice that the inner double summation Σ(j=0 to n-1) Σ(k=0 to n-1) (j OR k) is independent of i. Let's call this value S_or.

The key insight is that for any fixed value of j OR k, we can count how many (j, k) pairs produce that value. Due to symmetry in the OR operation, we can simplify our calculation.

For efficiency, we can precompute f[n] which represents Σ(i=0 to n-1) Σ(j=0 to i) (i OR j). Why up to i instead of n-1? Because (i OR j) where j <= i captures the essential pattern, and we can use symmetry to handle the full range.

The total sum for a given n can then be expressed as: Total Sum = f[n-1] * (n-1) * n / 2

This formula accounts for the multiplication by each i value and the proper counting of all (j, k) pairs.

Since the sum grows rapidly with n (approximately as n^5), and we want the maximum n where the sum doesn't exceed s, binary search becomes the natural choice. We can estimate that n won't exceed around 1330 based on the growth rate.

By preprocessing the values up to this maximum and then using binary search, we can efficiently find the largest valid n where the total sum stays within the limit s.

Learn more about Binary Search patterns.

Solution Implementation

1# Maximum array size to precompute
2MAX_SIZE = 1330
3
4# Precompute cumulative OR sums for all array sizes
5# cumulative_or_sum[i] = sum of all (j | k) for 0 <= j, k < i
6cumulative_or_sum = [0] * MAX_SIZE
7
8for array_size in range(1, MAX_SIZE):
9    # Start with previous cumulative sum
10    cumulative_or_sum[array_size] = cumulative_or_sum[array_size - 1] + array_size
11
12    # Add contribution of OR operations with the new element (array_size)
13    for element in range(array_size):
14        cumulative_or_sum[array_size] += 2 * (array_size | element)
15
16
17class Solution:
18    def maxSizedArray(self, s: int) -> int:
19        """
20        Find the maximum array size where the total cost doesn't exceed s.
21        Uses standard template: find first n where cost exceeds s.
22
23        The cost for an array of size n is calculated as:
24        cumulative_or_sum[n-1] * (n-1) * n // 2
25
26        Args:
27            s: Maximum allowed cost
28
29        Returns:
30            Maximum array size that satisfies the cost constraint
31        """
32        left, right = 1, MAX_SIZE - 1
33        first_exceed_index = -1  # First n where cost > s
34
35        # Binary search for first size where cost exceeds s
36        while left <= right:
37            mid = (left + right) // 2
38
39            # Check if array of size 'mid' exceeds the cost constraint
40            cost = cumulative_or_sum[mid - 1] * (mid - 1) * mid // 2
41
42            if cost > s:
43                # Feasible: cost exceeds limit
44                first_exceed_index = mid
45                right = mid - 1  # Look for earlier exceed
46            else:
47                # Not feasible: cost still valid
48                left = mid + 1
49
50        # Return one less than first exceed, or max if never exceeded
51        if first_exceed_index == -1:
52            return MAX_SIZE - 1
53        return first_exceed_index - 1
54
1class Solution {
2    // Maximum array size to precompute
3    private static final int MAX_SIZE = 1330;
4
5    // Precomputed values for each array size
6    // f[i] represents the sum: i + 2 * sum of (i | j) for all j from 0 to i-1
7    private static final long[] precomputedValues = new long[MAX_SIZE];
8
9    // Static initialization block to precompute values
10    static {
11        for (int i = 1; i < MAX_SIZE; ++i) {
12            // Start with the previous computed value plus current index
13            precomputedValues[i] = precomputedValues[i - 1] + i;
14
15            // Add twice the bitwise OR of current index with all previous indices
16            for (int j = 0; j < i; ++j) {
17                precomputedValues[i] += 2 * (i | j);
18            }
19        }
20    }
21
22    public int maxSizedArray(long s) {
23        // Binary search using standard template: find first n where cost > s
24        int left = 1;
25        int right = MAX_SIZE - 1;
26        int firstExceedIndex = -1;
27
28        while (left <= right) {
29            int mid = left + (right - left) / 2;
30
31            // Check if the computed value for size mid exceeds s
32            long cost = precomputedValues[mid - 1] * (mid - 1) * mid / 2;
33
34            if (cost > s) {
35                // Feasible: cost exceeds limit
36                firstExceedIndex = mid;
37                right = mid - 1;  // Look for earlier exceed
38            } else {
39                // Not feasible: cost still valid
40                left = mid + 1;
41            }
42        }
43
44        // Return one less than first exceed, or max if never exceeded
45        if (firstExceedIndex == -1) {
46            return MAX_SIZE - 1;
47        }
48        return firstExceedIndex - 1;
49    }
50}
51
1// Maximum array size constant
2const int MAX_SIZE = 1330;
3
4// Precomputed values for array size calculations
5// f[i] represents the sum of i plus all pairwise OR operations for elements 0 to i-1
6long long cumulativeOrSum[MAX_SIZE];
7
8// Initialize the precomputed values at compile time
9auto initializer = [] {
10    cumulativeOrSum[0] = 0;
11
12    for (int i = 1; i < MAX_SIZE; ++i) {
13        // Start with the sum from previous iteration plus current index
14        cumulativeOrSum[i] = cumulativeOrSum[i - 1] + i;
15
16        // Add twice the bitwise OR of current index with all previous indices
17        // (twice because each pair contributes to both elements)
18        for (int j = 0; j < i; ++j) {
19            cumulativeOrSum[i] += 2 * (i | j);
20        }
21    }
22    return 0;
23}();
24
25class Solution {
26public:
27    /**
28     * Finds the maximum size of an array that satisfies the given constraint.
29     * Uses standard template: find first n where cost > s.
30     *
31     * @param s The upper bound constraint value
32     * @return The maximum size of the array that satisfies the constraint
33     */
34    int maxSizedArray(long long s) {
35        int left = 1;
36        int right = MAX_SIZE - 1;
37        int firstExceedIndex = -1;
38
39        // Binary search for first size where cost exceeds s
40        while (left <= right) {
41            int mid = left + (right - left) / 2;
42
43            // Check if array of size 'mid' exceeds the constraint
44            long long cost = cumulativeOrSum[mid - 1] * (mid - 1) * mid / 2;
45
46            if (cost > s) {
47                // Feasible: cost exceeds limit
48                firstExceedIndex = mid;
49                right = mid - 1;  // Look for earlier exceed
50            } else {
51                // Not feasible: cost still valid
52                left = mid + 1;
53            }
54        }
55
56        // Return one less than first exceed, or max if never exceeded
57        if (firstExceedIndex == -1) {
58            return MAX_SIZE - 1;
59        }
60        return firstExceedIndex - 1;
61    }
62};
63
1// Maximum array size constant
2const MAX_SIZE = 1330;
3
4// Precomputed values array for optimization
5// f[i] represents the cumulative sum for size i
6const precomputedValues: bigint[] = Array(MAX_SIZE).fill(0n);
7
8// Initialize precomputed values using IIFE (Immediately Invoked Function Expression)
9(() => {
10    // Base case: empty array has sum 0
11    precomputedValues[0] = 0n;
12
13    // Calculate cumulative sums for each array size
14    for (let i = 1; i < MAX_SIZE; i++) {
15        // Start with previous sum plus current index
16        precomputedValues[i] = precomputedValues[i - 1] + BigInt(i);
17
18        // Add contribution from bitwise OR operations with all previous indices
19        for (let j = 0; j < i; j++) {
20            // Each OR operation contributes twice (for both i|j and j|i pairs)
21            precomputedValues[i] += BigInt(2) * BigInt(i | j);
22        }
23    }
24})();
25
26/**
27 * Finds the maximum sized array whose total sum does not exceed the given limit.
28 * Uses standard template: find first n where cost > s.
29 *
30 * @param s - The maximum allowed sum
31 * @returns The maximum array size that satisfies the sum constraint
32 */
33function maxSizedArray(s: number): number {
34    let left = 1;
35    let right = MAX_SIZE - 1;
36    let firstExceedIndex = -1;
37    const targetSum = BigInt(s);
38
39    // Binary search for first size where cost exceeds s
40    while (left <= right) {
41        const mid = Math.floor((left + right) / 2);
42
43        // Calculate the total sum for an array of size mid
44        const currentSum = (precomputedValues[mid - 1] * BigInt(mid - 1) * BigInt(mid)) / BigInt(2);
45
46        if (currentSum > targetSum) {
47            // Feasible: cost exceeds limit
48            firstExceedIndex = mid;
49            right = mid - 1;  // Look for earlier exceed
50        } else {
51            // Not feasible: cost still valid
52            left = mid + 1;
53        }
54    }
55
56    // Return one less than first exceed, or max if never exceeded
57    if (firstExceedIndex === -1) {
58        return MAX_SIZE - 1;
59    }
60    return firstExceedIndex - 1;
61}
62

Solution Approach

The solution consists of two main parts: preprocessing and binary search.

Preprocessing Phase:

First, we establish an upper bound for n. Since the sum grows approximately as (n-1)^5 / 4, and we need (n-1)^5 / 4 ≤ s, we can determine that n won't exceed approximately 1330 for reasonable values of s.

We precompute an array f where f[i] represents the sum Σ(j=0 to i) Σ(k=0 to j) (j OR k). The preprocessing code:

mx = 1330
f = [0] * mx
for i in range(1, mx):
    f[i] = f[i - 1] + i  # Add the case where j OR k = i (when j = k = i)
    for j in range(i):
        f[i] += 2 * (i | j)  # Count both (i, j) and (j, i) cases

The formula f[i] = f[i-1] + i + 2 * Σ(j=0 to i-1) (i OR j) builds upon the previous value and adds new contributions from index i.

Binary Search Phase:

Once we have the preprocessed values, we use binary search to find the maximum n such that the total sum doesn't exceed s.

For a given n, the total sum of the 3D array is calculated as: Total Sum = f[n-1] * (n-1) * n / 2

This formula accounts for:

  • f[n-1]: The sum pattern for OR operations
  • (n-1): Multiplication by each value of i from 0 to n-1
  • n / 2: Proper scaling factor for the 3D array structure

The binary search implementation uses the standard template. Since we want the maximum valid n, we find the first n where sum exceeds s:

def maxSizedArray(self, s: int) -> int:
    left, right = 1, mx
    first_exceed_index = -1  # First n where sum > s

    while left <= right:
        mid = (left + right) // 2
        cost = f[mid - 1] * (mid - 1) * mid // 2

        if cost > s:  # Feasible: sum exceeds s
            first_exceed_index = mid
            right = mid - 1  # Look for earlier exceed
        else:
            left = mid + 1  # Sum still valid, try larger

    # If never exceeded, return max; otherwise return one less than first exceed
    if first_exceed_index == -1:
        return mx
    return first_exceed_index - 1

The binary search finds the first n where the sum exceeds s, then returns first_exceed_index - 1 as the maximum valid n.

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 finding the maximum n for s = 10.

Step 1: Understanding the 3D Array

For n = 2, we calculate all elements:

  • When i = 0: All elements are 0 (since 0 * anything = 0)
  • When i = 1:
    • A[1][0][0] = 1 * (0 OR 0) = 1 * 0 = 0
    • A[1][0][1] = 1 * (0 OR 1) = 1 * 1 = 1
    • A[1][1][0] = 1 * (1 OR 0) = 1 * 1 = 1
    • A[1][1][1] = 1 * (1 OR 1) = 1 * 1 = 1

Total sum = 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 = 3

Step 2: Preprocessing Values

We build our f array:

  • f[0] = 0
  • f[1] = f[0] + 1 + 2*(1 OR 0) = 0 + 1 + 2*1 = 3
  • f[2] = f[1] + 2 + 2*(2 OR 0) + 2*(2 OR 1) = 3 + 2 + 2*2 + 2*3 = 3 + 2 + 4 + 6 = 15

Step 3: Binary Search

Now we search for maximum n where the sum ≤ 10:

Initial range: l = 1, r = 1330

First iteration:

  • m = (1 + 1330 + 1) / 2 = 666
  • Calculate sum for n = 666: This would be enormous, much greater than 10
  • Update: r = 665

After several iterations, we narrow down to:

  • When checking n = 2: Sum = f[1] * 1 * 2 / 2 = 3 * 1 * 1 = 3 ✓ (≤ 10)
  • When checking n = 3: Sum = f[2] * 2 * 3 / 2 = 15 * 2 * 3 / 2 = 45 ✗ (> 10)

Therefore, the maximum n = 2.

Verification: For n = 2, the total sum is 3, which is indeed ≤ 10. For n = 3, we would have a 3×3×3 array where the sum would be 45, exceeding our limit. Thus, n = 2 is the correct answer.

Time and Space Complexity

The time complexity consists of two parts:

  1. Preprocessing phase: The outer loop runs from 1 to mx-1 (i.e., O(mx) iterations). For each iteration i, the inner loop runs i times, performing a bitwise OR operation and arithmetic operations. This results in 1 + 2 + 3 + ... + (mx-1) = (mx-1) * mx / 2 operations, giving us O(mx^2) time complexity for preprocessing.

  2. Binary search phase: The maxSizedArray method performs a binary search between 1 and mx. Each iteration of the while loop reduces the search space by half, resulting in O(log mx) time complexity.

Therefore, the total time complexity is O(mx^2 + log mx). Since mx = 1330 is a constant, we can also express this as O(n^2 + log n) where n represents the upper bound of the search range.

The space complexity is O(mx) or O(n), as we allocate an array f of size mx to store the precomputed values. No additional space that scales with input is used during the binary search phase.

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

Common Pitfalls

1. Using Wrong Binary Search Template Variant

Pitfall: Using while left < right with left = mid for finding the maximum valid n:

# WRONG: Non-standard template for finding maximum
while left < right:
    mid = (left + right + 1) >> 1  # Need ceiling division
    if cost <= s:
        left = mid
    else:
        right = mid - 1
return left

Solution: Use the standard template by finding the first n where cost exceeds s:

# CORRECT: Standard template
first_exceed_index = -1
while left <= right:
    mid = (left + right) // 2
    if cost > s:  # Feasible: exceeds limit
        first_exceed_index = mid
        right = mid - 1
    else:
        left = mid + 1
return first_exceed_index - 1 if first_exceed_index != -1 else MAX_SIZE - 1

2. Integer Overflow in Cost Calculation

Pitfall: The most critical issue in this solution is potential integer overflow when calculating the cost:

cost = cumulative_or_sum[mid - 1] * (mid - 1) * mid // 2

For large values of mid (approaching 1330), the multiplication cumulative_or_sum[mid - 1] * (mid - 1) * mid can exceed Python's integer limits in other languages or cause performance issues even in Python with very large numbers.

Solution: Rearrange the calculation to perform division earlier or check for overflow:

# Option 1: Divide earlier to reduce intermediate values
cost = cumulative_or_sum[mid - 1] * ((mid - 1) * mid // 2)

# Option 2: Check if multiplication would exceed s before computing
if cumulative_or_sum[mid - 1] > s * 2 // ((mid - 1) * mid):
    right = mid - 1
    continue

3. Incorrect Precomputation Formula

Pitfall: The precomputation loop might be implemented incorrectly:

# Wrong: Missing the factor of 2 for symmetric pairs
for array_size in range(1, MAX_SIZE):
    cumulative_or_sum[array_size] = cumulative_or_sum[array_size - 1] + array_size
    for element in range(array_size):
        cumulative_or_sum[array_size] += (array_size | element)  # Missing factor of 2!

This misses that for each unique OR value, we need to count both (j, k) and (k, j) pairs when j ≠ k.

Solution: Ensure the factor of 2 is included for non-diagonal elements:

for array_size in range(1, MAX_SIZE):
    cumulative_or_sum[array_size] = cumulative_or_sum[array_size - 1] + array_size
    for element in range(array_size):
        cumulative_or_sum[array_size] += 2 * (array_size | element)  # Correct

4. Hardcoded Maximum Size Without Validation

Pitfall: Using a fixed MAX_SIZE = 1330 without considering the actual input range. If s is extremely large (beyond what 1330 can handle), the solution would return an incorrect answer.

Solution: Dynamically determine the upper bound based on s:

def maxSizedArray(self, s: int) -> int:
    # Dynamically calculate upper bound
    # Since sum ~ n^5/4, we have n ~ (4*s)^(1/5)
    import math
    max_possible = min(MAX_SIZE, int((4 * s) ** 0.2) + 10)  # Add buffer

    left, right = 1, max_possible
    # ... rest of binary search

5. Not Handling Edge Cases

Pitfall: Not properly handling small values of s:

  • When s = 0, the answer should be 1 (array of size 1 has sum 0)
  • When s < 0, the input is invalid

Solution: Add edge case handling:

def maxSizedArray(self, s: int) -> int:
    if s == 0:
        return 1
    if s < 0:
        raise ValueError("s must be non-negative")

    # Continue with normal binary search...
Loading...
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