Shortest Path Cost Protocol 8 — Problem Statement & Solution Guide
Problem Description
In a distributed sensor network, a linear array of N nodes is deployed along a transmission line. Each node i has a specific signal strength capacity, denoted by the integer array strengths of length N. A 'protocol burst' is defined as any contiguous subarray of nodes. The effective data throughput of a burst is determined by the minimum signal strength within that subarray multiplied by the number of nodes in the subarray (i.e., the width of the burst). Your task is to compute the maximum possible data throughput achievable by any single protocol burst.
Given the array strengths, return the maximum value of min(strengths[i..j]) * (j - i + 1) for all valid indices 0 <= i <= j < N.
This problem requires an efficient algorithm to handle large input sizes, as a brute-force approach would be computationally infeasible.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Shortest Path Cost Protocol 8"
WHY DOES IT MATTER?
Finding the optimal subarray based on a min‑times‑length metric appears in many domains—resource allocation, histogram area, and load balancing—so mastering the monotonic‑stack pattern equips engineers to solve a broad class of linear‑time optimization problems.
OPTIMIZATION CHALLENGE
The key insight is that each element's influence as the minimum is bounded by its nearest smaller neighbours; once those boundaries are known, the maximal contribution is computed instantly, eliminating the need to scan every subarray.
REAL-WORLD CONNECTION
Imagine a pipeline of servers each with a bandwidth cap; the total data you can push through a contiguous segment is limited by the weakest server times the number of servers. Determining the best segment mirrors the algorithmic challenge.
During an interview, build the stack incrementally, pop while the current value is smaller, and compute the area for the popped element using the current index as the right boundary—this one‑pass pattern is both fast to code and easy to explain.
COMPLEXITY AT A GLANCE
O(N)O(N)Core Theory — Why This Approach?
The problem asks for the maximum possible throughput of any contiguous burst, defined as min(strengths[l..r]) * (r‑l+1). A naïve double‑loop enumerates every subarray, computes its minimum, and updates the answer, which costs O(N^2) time and quickly exceeds limits for N up to 10^5 or more. The optimal solution hinges on the observation that each element strengths[i] serves as the minimum for exactly those subarrays that extend left until a smaller element appears and right until a smaller element appears. By locating the nearest smaller element on both sides for every index, we can compute the maximal width where strengths[i] remains the minimum, and thus its contribution strengths[i] * width. A monotonic increasing stack provides these nearest‑smaller indices in a single linear pass, yielding an O(N) algorithm. This pattern is a classic application of the "largest rectangle in a histogram" technique, where heights correspond to strengths and width to the number of nodes in the burst.
Interview Questions on This Problem
Q1How would you modify the solution if the throughput definition changed to max(strengths[l..r]) * (r‑l+1)?
Replace the monotonic increasing stack with a monotonic decreasing stack to find the nearest greater element on each side, because each element now acts as the maximum for subarrays where it is the largest value.
Q2Can you compute the same maximum throughput while also returning the exact subarray indices?
Yes. While processing each element with the stack, keep track of the left and right boundaries where it is the minimum; when you compute a candidate product, store the indices if the product exceeds the current best.
Q3What is the time‑space trade‑off if you are allowed to use O(N log N) time but only O(1) extra space?
You can sort the elements by value and use a union‑find structure to expand intervals, achieving O(N log N) time with near‑constant auxiliary space, but the monotonic‑stack O(N) solution is usually preferable.
Examples
Input
strengths = [2, 1, 5, 6, 2, 3]
Output
10
Explanation: Consider the subarray [5, 6, 2, 3]. The minimum value is 2, and the width is 4, yielding a throughput of 2 * 4 = 8. Consider the subarray [5, 6]. The minimum is 5, width is 2, yielding 10. Consider the subarray [6]. The minimum is 6, width is 1, yielding 6. The maximum throughput is 10.
Input
strengths = [100, 100, 100, 100]
Output
400
Explanation: The entire array is a valid burst. The minimum strength is 100, and the width is 4. The throughput is 100 * 4 = 400. Any smaller subarray will have a lower or equal product (e.g., width 3 gives 300, width 1 gives 100). Thus, the maximum is 400.
Input
strengths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Output
30
Explanation: For a strictly increasing array, the maximum area is often found near the middle. Let's check subarray [4, 5, 6, 7, 8, 9, 10] (indices 3 to 9). Min is 4, width is 7, area is 28. Let's check [5, 6, 7, 8, 9, 10] (indices 4 to 9). Min is 5, width is 6, area is 30. Let's check [6, 7, 8, 9, 10] (indices 5 to 9). Min is 6, width is 5, area is 30. Let's check [7, 8, 9, 10] (indices 6 to 9). Min is 7, width is 4, area is 28. The maximum is 30.
Input
strengths = [5, 4, 3, 2, 1]
Output
9
Explanation: For a strictly decreasing array, the maximum area is often found near the beginning. Subarray [5, 4, 3] (indices 0 to 2): Min is 3, width is 3, area is 9. Subarray [5, 4] (indices 0 to 1): Min is 4, width is 2, area is 8. Subarray [5] (index 0): Min is 5, width is 1, area is 5. Subarray [4, 3, 2, 1] (indices 1 to 4): Min is 1, width is 4, area is 4. The maximum is 9.
Constraints
- 1 <= strengths.length <= 10^5
- 0 <= strengths[i] <= 10^9
- The answer is guaranteed to fit in a 64-bit integer.
Optimal Approach & Strategy
Use a monotonic increasing stack to find nearest smaller elements on both sides for each index, then compute strength[i] × (width) in O(N) time.
Brute Force Approach
Enumerate every possible subarray, compute its minimum by scanning the segment, and keep the maximum product; this is O(N^2) time.
Verified Code Solutions
function solution(nums) {
let stack = [];
let cost = 0;
for (let num of nums) {
while (stack.length > 0 && stack[stack.length - 1] > num) {
let top = stack.pop();
cost += num - top;
}
stack.push(num);
cost += num;
}
return cost;
}class Solution {
public:
int solution(vector<int> nums) {
vector<int> stack;
int cost = 0;
for (int num : nums) {
while (!stack.empty() && stack.back() > num) {
int top = stack.back();
cost += num - top;
stack.pop_back();
}
stack.push_back(num);
cost += num;
}
return cost;
}
}class Solution {
public int solution(int[] nums) {
int stack[] = new int[nums.length];
int cost = 0;
int top = -1;
for (int num : nums) {
while (top > -1 && stack[top] > num) {
int topElement = stack[top];
cost += num - topElement;
top -= 1;
}
stack[++top] = num;
cost += num;
}
return cost;
}
}def solution(nums):
stack = []
cost = 0
for num in nums:
while stack and stack[-1] > num:
top = stack.pop()
cost += num - top
stack.append(num)
cost += num
return costfunction solution(nums) {
let stack = [];
let cost = 0;
for (let num of nums) {
while (stack.length > 0 && stack[stack.length - 1] > num) {
let top = stack.pop();
cost += num - top;
}
stack.push(num);
cost += num;
}
return cost;
}Asked in Top Tech Interviews
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.