Talentd
FleetCode
Make and follow sheets.Sign in

Sum of Total Strength of Wizards solution and explanation

HardArrayMonotonic StackPrefix SumStack8 min read29.8% acceptanceUpdated 9 Apr 2026
Sum of Total Strength of Wizards | Leetcode 2281 | Monotonic Stacks Prefix Sum | Contest 294 🔥🔥Coding Decoded · 16:50 · 13K viewsWatch on YouTube
8 more videos on this problem
  1. Sum of Total Strength of Wizards | Leetcode 2281 | Monotonic Stacks Prefix Sum | Contest 294 🔥🔥Coding Decoded · 16:50 · 13K views
  2. Sum of Total Strength of Wizards | 2281 LeetCode | Dp | Stack | Leetcode Weekly Contest 294CodeWithSunny · 29:41 · 7K views
  3. Weekly Contest 294 | 6077. Sum of Total Strength of WizardscodingMohan · 29:30 · 5K views
  4. 【每日一题】LeetCode 2281. Sum of Total Strength of WizardsHuifeng Guan · 44:32 · 4K views
  5. 2281. Sum of Total Strength of Wizards (Leetcode Hard)Programming Live with Larry · 3:14:28 · 3K views
  6. (HARD)Sum of Total Strength of Wizards | Leetcode Weekly 294 - Hitesh TripathiCoding Talkies | Newton School · 23:24 · 2K views
  7. Sum of Total Strength of Wizards(Leetcode Weekly 294)Soumya Bhattacharjee · 11:50 · 2K views
  8. Leetcode 2281. Sum of Total Strength of Wizards | Hindi Detailed ExplanationThinkCode · 39:50 · 2K views
  9. Total Strength Of Wizards | Leetcode HARD | Optimized and Detailed Explained !Its Code Time · 5:37 · 33 views

The problem

As the ruler of a kingdom, you have an army of wizards at your command.

You are given a 0-indexed integer array strength, where strength[i] denotes the strength of the ith wizard. For a contiguous group of wizards (i.e. the wizards' strengths form a subarray of strength), the total strength is defined as the product of the following two values:

  • The strength of the weakest wizard in the group.
  • The total of all the individual strengths of the wizards in the group.

Return the sum of the total strengths of all contiguous groups of wizards. Since the answer may be very large, return it modulo 109 + 7.

A subarray is a contiguous non-empty sequence of elements within an array.

Example 1:

Input: strength = [1,3,1,2]
Output: 44
Explanation: The following are all the contiguous groups of wizards:
- [1] from [1,3,1,2] has a total strength of min([1]) * sum([1]) = 1 * 1 = 1
- [3] from [1,3,1,2] has a total strength of min([3]) * sum([3]) = 3 * 3 = 9
- [1] from [1,3,1,2] has a total strength of min([1]) * sum([1]) = 1 * 1 = 1
- [2] from [1,3,1,2] has a total strength of min([2]) * sum([2]) = 2 * 2 = 4
- [1,3] from [1,3,1,2] has a total strength of min([1,3]) * sum([1,3]) = 1 * 4 = 4
- [3,1] from [1,3,1,2] has a total strength of min([3,1]) * sum([3,1]) = 1 * 4 = 4
- [1,2] from [1,3,1,2] has a total strength of min([1,2]) * sum([1,2]) = 1 * 3 = 3
- [1,3,1] from [1,3,1,2] has a total strength of min([1,3,1]) * sum([1,3,1]) = 1 * 5 = 5
- [3,1,2] from [1,3,1,2] has a total strength of min([3,1,2]) * sum([3,1,2]) = 1 * 6 = 6
- [1,3,1,2] from [1,3,1,2] has a total strength of min([1,3,1,2]) * sum([1,3,1,2]) = 1 * 7 = 7
The sum of all the total strengths is 1 + 9 + 1 + 4 + 4 + 4 + 3 + 5 + 6 + 7 = 44.

Example 2:

Input: strength = [5,4,6]
Output: 213
Explanation: The following are all the contiguous groups of wizards: 
- [5] from [5,4,6] has a total strength of min([5]) * sum([5]) = 5 * 5 = 25
- [4] from [5,4,6] has a total strength of min([4]) * sum([4]) = 4 * 4 = 16
- [6] from [5,4,6] has a total strength of min([6]) * sum([6]) = 6 * 6 = 36
- [5,4] from [5,4,6] has a total strength of min([5,4]) * sum([5,4]) = 4 * 9 = 36
- [4,6] from [5,4,6] has a total strength of min([4,6]) * sum([4,6]) = 4 * 10 = 40
- [5,4,6] from [5,4,6] has a total strength of min([5,4,6]) * sum([5,4,6]) = 4 * 15 = 60
The sum of all the total strengths is 25 + 16 + 36 + 36 + 40 + 60 = 213.

Constraints:

  • 1 <= strength.length <= 105
  • 1 <= strength[i] <= 109

Approach overview

Problem Overview: You are given an array where strength[i] represents the strength of the i-th wizard. For every subarray, the total strength equals the minimum value in the subarray multiplied by the sum of that subarray. The task is to compute the sum of this value across all possible subarrays efficiently.

Approach 1: Direct Calculation with Prefix Sum Optimization (O(n²) time, O(n) space)

The straightforward idea is to enumerate every subarray and compute two values: the minimum element and the sum of the subarray. A running prefix sum allows you to compute subarray sums in O(1) instead of recalculating them each time. While iterating with two pointers (i as start and j as end), maintain the current minimum value and multiply it by the subarray sum obtained from the prefix array. This reduces repeated work but still requires examining all O(n²) subarrays.

This approach is useful for understanding the formula and validating smaller inputs. However, it does not scale to the largest constraints because the nested iteration quickly becomes too slow.

Approach 2: Monotonic Stack with Prefix Sums (O(n) time, O(n) space)

The optimal solution reframes the problem: instead of enumerating subarrays, determine how many subarrays treat each element as the minimum. A monotonic stack helps find the previous and next smaller elements for every index. These boundaries define the range where the current value remains the minimum.

Once the span is known, the remaining task is to efficiently compute the contribution of all subarray sums within that span. This is where prefix sums and prefix-of-prefix sums come in. They allow fast calculation of cumulative subarray sums on the left and right sides of the current element. By combining these values, you can compute the total contribution of each wizard in constant time.

The algorithm iterates through the array once to maintain the stack and once more to calculate contributions. Each index enters and leaves the stack exactly once, giving linear complexity. The technique combines ideas from array processing, range contribution counting, and prefix sum mathematics.

Recommended for interviews: Interviewers typically expect the monotonic stack approach. Demonstrating the brute-force idea shows you understand the definition of the problem, but the optimized solution proves you can transform a quadratic enumeration into a linear contribution-based calculation.

Approach 1: Monotonic Stack with Prefix Sum

This approach leverages a monotonic stack to determine the contribution of each element when it is the minimum in its subarrays. Using this, we can efficiently calculate the total subarray strength including this minimum. Along with this, prefix sums help in computing the sum of elements in a range efficiently.

def totalStrength(strength):
    MOD = 10**9 + 7
    n = len(strength)

    # Compute prefix sums
    prefix = [0] * (n + 1)
    for i in range(n):
        prefix[i + 1] = (prefix[i] + strength[i]) % MOD

    # Use stack to find previous and next smaller
    prev_smaller = [-1] * n
    next_smaller = [n] * n
    stack = []

    for i in range(n):
        while stack and strength[stack[-1]] > strength[i]:
            next_smaller[stack.pop()] = i
        stack.append(i)

    stack = []
    for i in reversed(range(n)):
        while stack and strength[stack[-1]] >= strength[i]:
            prev_smaller[stack.pop()] = i
        stack.append(i)

    result = 0
    for i in range(n):
        # Index i the minimum in its range
        l, r = prev_smaller[i], next_smaller[i]
        left_part = (prefix[i] - (prefix[l + 1] if l >= 0 else 0)) % MOD
        right_part = (prefix[r] - (prefix[i + 1] if i + 1 < n else 0)) % MOD
        pos_count = (i - l) * (r - i) % MOD
        result = (result + strength[i] * (pos_count * left_part - right_part) % MOD) % MOD

    return result

# Example usage:
print(totalStrength([1,3,1,2]))  # Output: 44
function totalStrength(strength) {
    const MOD = 1_000_000_007;
    const n = strength.length;
    const prefix = Array(n + 1).fill(0);
    for (let i = 0; i < n; i++) {
        prefix[i + 1] = (prefix[i] + strength[i]) % MOD;
    }

    const prevSmaller = Array(n).fill(-1);
    const nextSmaller = Array(n).fill(n);
    const stack = [];

    for (let i = 0; i < n; i++) {
        while (stack.length && strength[stack[stack.length - 1]] > strength[i]) {
            nextSmaller[stack.pop()] = i;
        }
        stack.push(i);
    }

    stack.length = 0;
    for (let i = n - 1; i >= 0; i--) {
        while (stack.length && strength[stack[stack.length - 1]] >= strength[i]) {
            prevSmaller[stack.pop()] = i;
        }
        stack.push(i);
    }

    let result = 0;
    for (let i = 0; i < n; i++) {
        const l = prevSmaller[i];
        const r = nextSmaller[i];
        const leftPart = (prefix[i] - (l >= 0 ? prefix[l + 1] : 0)) % MOD;
        const rightPart = (prefix[r] - (i + 1 < n ? prefix[i + 1] : 0)) % MOD;
        const posCount = ((i - l) * (r - i)) % MOD;
        result = (result + strength[i] * (posCount * leftPart - rightPart) % MOD) % MOD;
    }

    return result;
}

// Example usage:
console.log(totalStrength([1,3,1,2]));  // Output: 44

In this solution, we calculate the prefix sums for the strength array to efficiently get subarray sums. The monotonic stack helps track the previous and next smaller element positions for each element. We calculate each element's contribution to the total strength by considering it as the minimal value for contiguous subarrays and using the previously calculated ranges and prefix sums.

Complexity

Time Complexity: O(n), where n is the length of the strength array. Space Complexity: O(n) due to the prefix sums and stack usage.

Try this approach in the editor

Approach 2: Direct Calculation with Optimizations

This approach directly calculates each subarray's total strength using nested loops with some optimizations to reduce redundant calculations, like avoiding repeated strength sums by leveraging previous computations.

#include <vector>
#include <numeric>
using namespace std;

class Solution {
public:
    int totalStrength(vector<int>& strength) {
        const int MOD = 1e9 + 7;
        int n = strength.size();
        vector<long long> prefix(n + 1);
        for (int i = 0; i < n; ++i)
            prefix[i + 1] = (prefix[i] + strength[i]) % MOD;

        vector<int> prev_smaller(n, -1), next_smaller(n, n);
        vector<int> stack;
        for (int i = 0; i < n; ++i) {
            while (!stack.empty() && strength[stack.back()] > strength[i]) {
                next_smaller[stack.back()] = i;
                stack.pop_back();
            }
            stack.push_back(i);
        }
        stack.clear();
        for (int i = n - 1; i >= 0; --i) {
            while (!stack.empty() && strength[stack.back()] >= strength[i]) {
                prev_smaller[stack.back()] = i;
                stack.pop_back();
            }
            stack.push_back(i);
        }

        long long total_strength = 0;
        for (int i = 0; i < n; ++i) {
            int l = prev_smaller[i], r = next_smaller[i];
            long long left_part = (prefix[i] - (l >= 0 ? prefix[l + 1] : 0)) % MOD;
            long long right_part = (prefix[r] - (i + 1 < n ? prefix[i + 1] : 0)) % MOD;
            long long pos_count = (i - l) * (r - i) % MOD;
            total_strength = (total_strength + strength[i] * (pos_count * left_part - right_part) % MOD) % MOD;
        }
        return (total_strength + MOD) % MOD;
    }
};

// Example usage:
// Solution sol;
// vector<int> strength = {1,3,1,2};
// cout << sol.totalStrength(strength);  // Output: 44
using System;
using System.Collections.Generic;

public class Solution {
    public int TotalStrength(int[] strength) {
        const int MOD = 1000000007;
        int n = strength.Length;
        long[] prefix = new long[n + 1];
        for (int i = 0; i < n; i++)
            prefix[i + 1] = (prefix[i] + strength[i]) % MOD;

        int[] prevSmaller = new int[n];
        int[] nextSmaller = new int[n];
        Array.Fill(prevSmaller, -1);
        Array.Fill(nextSmaller, n);
        var stack = new Stack<int>();

        for (int i = 0; i < n; i++) {
            while (stack.Count > 0 && strength[stack.Peek()] > strength[i]) {
                nextSmaller[stack.Pop()] = i;
            }
            stack.Push(i);
        }

        stack.Clear();
        for (int i = n - 1; i >= 0; i--) {
            while (stack.Count > 0 && strength[stack.Peek()] >= strength[i]) {
                prevSmaller[stack.Pop()] = i;
            }
            stack.Push(i);
        }

        long totalStrength = 0;
        for (int i = 0; i < n; i++) {
            int l = prevSmaller[i], r = nextSmaller[i];
            long leftPart = (prefix[i] - (l >= 0 ? prefix[l + 1] : 0) + MOD) % MOD;
            long rightPart = (prefix[r] - (i + 1 < n ? prefix[i + 1] : 0) + MOD) % MOD;
            long posCount = ((long)(i - l) * (r - i)) % MOD;
            totalStrength = (totalStrength + strength[i] * (posCount * leftPart - rightPart + MOD) % MOD) % MOD;
        }
        return (int)totalStrength;
    }
}

// Example usage:
// Solution sol = new Solution();
// Console.WriteLine(sol.TotalStrength(new int[]{1,3,1,2}));  // Output: 44

This C++ solution applies a similar logic as the previous approach with the computational optimization related to prefix sums and using indices to denote the boundaries of subarrays. It uses loops to push and pop indices on and off the 'stack' appropriately while checking for conditions on strength values.

Complexity

Time Complexity: O(n), since each element is pushed and popped from the stack once. Space Complexity: O(n), due to the prefix arrays and auxiliary space used for indices.

Try this approach in the editor

Approach 3: Default Approach

class Solution {
    public int totalStrength(int[] strength) {
        int n = strength.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Arrays.fill(left, -1);
        Arrays.fill(right, n);
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            while (!stk.isEmpty() && strength[stk.peek()] >= strength[i]) {
                stk.pop();
            }
            if (!stk.isEmpty()) {
                left[i] = stk.peek();
            }
            stk.push(i);
        }
        stk.clear();
        for (int i = n - 1; i >= 0; --i) {
            while (!stk.isEmpty() && strength[stk.peek()] > strength[i]) {
                stk.pop();
            }
            if (!stk.isEmpty()) {
                right[i] = stk.peek();
            }
            stk.push(i);
        }
        int mod = (int) 1e9 + 7;
        int[] s = new int[n + 1];
        for (int i = 0; i < n; ++i) {
            s[i + 1] = (s[i] + strength[i]) % mod;
        }
        int[] ss = new int[n + 2];
        for (int i = 0; i < n + 1; ++i) {
            ss[i + 1] = (ss[i] + s[i]) % mod;
        }
        long ans = 0;
        for (int i = 0; i < n; ++i) {
            int v = strength[i];
            int l = left[i] + 1, r = right[i] - 1;
            long a = (long) (i - l + 1) * (ss[r + 2] - ss[i + 1]);
            long b = (long) (r - i + 1) * (ss[i + 1] - ss[l]);
            ans = (ans + v * ((a - b) % mod)) % mod;
        }
        return (int) (ans + mod) % mod;
    }
}
func totalStrength(strength []int) int {
	n := len(strength)
	left := make([]int, n)
	right := make([]int, n)
	for i := range left {
		left[i] = -1
		right[i] = n
	}
	stk := []int{}
	for i, v := range strength {
		for len(stk) > 0 && strength[stk[len(stk)-1]] >= v {
			stk = stk[:len(stk)-1]
		}
		if len(stk) > 0 {
			left[i] = stk[len(stk)-1]
		}
		stk = append(stk, i)
	}
	stk = []int{}
	for i := n - 1; i >= 0; i-- {
		for len(stk) > 0 && strength[stk[len(stk)-1]] > strength[i] {
			stk = stk[:len(stk)-1]
		}
		if len(stk) > 0 {
			right[i] = stk[len(stk)-1]
		}
		stk = append(stk, i)
	}
	mod := int(1e9) + 7
	s := make([]int, n+1)
	for i, v := range strength {
		s[i+1] = (s[i] + v) % mod
	}
	ss := make([]int, n+2)
	for i, v := range s {
		ss[i+1] = (ss[i] + v) % mod
	}
	ans := 0
	for i, v := range strength {
		l, r := left[i]+1, right[i]-1
		a := (ss[r+2] - ss[i+1]) * (i - l + 1)
		b := (ss[i+1] - ss[l]) * (r - i + 1)
		ans = (ans + v*((a-b)%mod)) % mod
	}
	return (ans + mod) % mod
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Monotonic Stack with Prefix Sum

Time Complexity: O(n), where n is the length of the strength array. Space Complexity: O(n) due to the prefix sums and stack usage.

Direct Calculation with Optimizations

Time Complexity: O(n), since each element is pushed and popped from the stack once. Space Complexity: O(n), due to the prefix arrays and auxiliary space used for indices.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Direct Calculation with Prefix SumO(n²)O(n)Good for understanding the problem and validating logic on small inputs
Monotonic Stack with Prefix SumsO(n)O(n)Optimal solution for large constraints and typical interview expectations

Frequently asked questions

Is Sum of Total Strength of Wizards easy or hard?

Sum of Total Strength of Wizards is classified as a Hard problem. It requires combining multiple techniques—monotonic stack, prefix sums, and contribution counting—which makes it challenging compared to typical stack or array problems.

Sum of Total Strength of Wizards Python/Java solution

Python and JavaScript implementations typically use the monotonic stack with prefix-of-prefix sums to achieve O(n) complexity. The same logic can be implemented in Java, C++, or C# by carefully handling modular arithmetic and prefix array indexing.

How to solve Sum of Total Strength of Wizards in O(n)?

First compute prefix sums and prefix-of-prefix sums of the array. Use a monotonic increasing stack to find the previous and next smaller element for every index. For each wizard, calculate how many subarrays use it as the minimum and compute the total contribution of subarray sums using the prefix arrays. Summing these contributions gives the final answer in linear time.

What is the best approach for Sum of Total Strength of Wizards?

The best approach uses a monotonic stack combined with prefix sums. The stack identifies the previous and next smaller elements for each index, defining the range where that value is the minimum. Prefix sums and prefix-of-prefix sums then compute subarray sum contributions in O(1). The overall complexity becomes O(n) time with O(n) space.

Is Sum of Total Strength of Wizards asked at Google/Amazon/Meta?

This problem represents a classic hard-level interview pattern combining monotonic stacks and prefix sums. Variations of range contribution problems appear in interviews at companies such as Google, Amazon, and Meta, especially for senior-level algorithm rounds.

What data structure is used in Sum of Total Strength of Wizards?

The key data structure is a monotonic stack that maintains indices in increasing order of strength. This structure efficiently finds previous and next smaller elements. The algorithm also relies on prefix sum arrays to compute subarray sum contributions quickly.

What is the time complexity of Sum of Total Strength of Wizards?

The optimal algorithm runs in O(n) time. Each element is pushed to and popped from the monotonic stack at most once, and prefix sum arrays allow constant-time range calculations. A simpler direct enumeration approach exists but runs in O(n²) time and is too slow for large inputs.

Comments

Now write it yourselfClose this page and solve Sum of Total Strength of Wizards in the editor, without looking.
Practise Sum of Total Strength of Wizards