Circular Array Subset Sum — Problem Statement & Solution Guide

ArraysMediumTwo Pointers
TimeO(n)
|
SpaceO(1)

Quick Answer & Algorithm Key Takeaway

Master coding challenges related to Arrays and solve the Circular Array Subset Sum problem optimally.

TopicArrays
PatternTwo Pointers
TimeO(n)
SpaceO(1)

Problem Description

You are given an integer array weights that represents a circular sequence and an integer capacity. Your task is to select a non‑empty contiguous segment of the circular array whose element sum does not exceed capacity and is as large as possible. Because the array is circular, the segment may start near the end and continue at the beginning. Return the maximum achievable sum. If every single element is larger than capacity, return 0.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Circular Array Subset Sum"

medium

WHY DOES IT MATTER?

Sliding‑window on a circular structure is a core pattern for any problem that asks for a contiguous sub‑range with a bounded aggregate (sum, weight, time), common in networking, budgeting, and streaming analytics.

OPTIMIZATION CHALLENGE

The key insight is to linearize the circular array by duplicating it, which lets a simple monotonic two‑pointer scan enforce the capacity constraint without ever revisiting an element, collapsing an O(n^2) search into O(n).

REAL-WORLD CONNECTION

Think of a token‑ring network where a fixed amount of bandwidth (capacity) can be allocated to a consecutive set of nodes; the optimal allocation is exactly the maximum‑weight contiguous ring segment that does not exceed the bandwidth cap.

During implementation keep the left pointer strictly non‑decreasing; if the window ever reaches size n you can stop because any longer window would repeat elements and cannot improve the sum.

COMPLEXITY AT A GLANCE

⏱ Time:O(n)
💾 Space:O(1)

Core Theory — Why This Approach?

The task is a bounded‑capacity variant of the classic maximum‑sum subarray problem, but the array is circular, so a segment may wrap from the end to the beginning. A naïve solution enumerates every possible start index and expands to every possible end index, computing the sum each time; this O(n^2) approach quickly exceeds time limits for typical interview constraints (n up to 10^5 or more). The optimal paradigm treats the circular structure by conceptually concatenating the array to itself, creating a linear view of length 2n, and then applies a sliding‑window (two‑pointer) technique. The window’s sum is increased by moving the right pointer; if the sum exceeds the capacity, the left pointer is advanced until the sum is back within the limit, guaranteeing each element is visited at most twice, yielding O(n) time and O(1) extra space. An alternative using prefix sums with binary search also works in O(n log n), but the linear two‑pointer method is simpler and faster in practice.

Interview Questions on This Problem

Q1How would you modify the solution to also return the length of the longest segment when multiple segments achieve the same maximum sum?

Track both the current sum and the window length; when you update the global maximum sum, store the corresponding length, and if you encounter the same sum later, keep the larger length. The two‑pointer loop naturally provides the window length as right‑left+1.

Q2What changes are required if the capacity can be negative, meaning you must pick a segment whose sum is ≤ a negative bound?

When capacity is negative, any positive element immediately violates the bound, so the sliding window must shrink aggressively. The algorithm still works: the window will only contain non‑positive numbers, and you may need to reset the window when a single element exceeds the capacity.

Q3If the interview asks for the actual start and end indices of the optimal segment in the original circular array, how do you report them?

Maintain the best window’s left and right pointers while iterating over the duplicated array. When reporting, map the left index modulo n to the original array and compute the length; if the segment wraps, the end index will be (left+length‑1) mod n.

Examples

Example 1

Input

weights = [4,2,1,7,3], capacity = 10

Output

10

Explanation: The sub‑array [2,1,7] sums to 10, which equals the capacity and is the largest possible sum not exceeding 10. Other candidates such as [4,2,1,3] (wrapping) also sum to 10, so the answer is 10.

Example 2

Input

weights = [5,-2,3,6], capacity = 8

Output

7

Explanation: Including the negative value helps keep the sum low. The segment [-2,3,6] sums to 7, which is the highest sum ≤8. No other contiguous segment yields a larger valid sum.

Example 3

Input

weights = [9,12,15], capacity = 8

Output

0

Explanation: Each individual element exceeds the capacity, therefore no valid non‑empty segment exists and the result is 0.

Constraints

  • 1 <= weights.length <= 100000
  • -10^9 <= weights[i] <= 10^9
  • 0 <= capacity <= 10^14

Optimal Approach & Strategy

Duplicate the array to length 2n, then run a two‑pointer sliding window that expands right and contracts left whenever the sum exceeds capacity, updating the answer on each step; this runs in O(n) time and O(1) extra space.

Brute Force Approach

Enumerate every possible start index, then for each start expand forward up to n elements, accumulating the sum and tracking the best sum that stays ≤ capacity; this checks O(n^2) windows.

Code Solutions

JavaScript Solution
Time: O(n)
/**
 * @param {number[]} weights
 * @param {number} capacity
 * @return {number}
 */
var maxCircularSum = function(weights, capacity) {
    const n = weights.length;
    if (n === 0) return 0;
    
    // Find max single element that fits
    let maxSingle = -Infinity;
    for (let i = 0; i < n; i++) {
        if (weights[i] <= capacity) {
            maxSingle = Math.max(maxSingle, weights[i]);
        }
    }
    
    // Sliding window on doubled array
    let maxSum = maxSingle;
    let left = 0;
    let currentSum = 0;
    
    for (let right = 0; right < 2 * n; right++) {
        currentSum += weights[right % n];
        
        while (left <= right && (currentSum > capacity || right - left + 1 > n)) {
            currentSum -= weights[left % n];
            left++;
        }
        
        if (currentSum <= capacity) {
            maxSum = Math.max(maxSum, currentSum);
        }
    }
    
    return maxSum;
};

// Example driver code
const weights = [4, 2, 1, 7, 3];
const capacity = 10;
console.log(maxCircularSum(weights, capacity));

Asked in Top Tech Interviews

Paytm

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.