LeetCode 2908 - Minimum Sum of Mountain Triplets I
The problem asks us to find the minimum possible sum of a "mountain triplet" within a given array of integers. A mountain triplet is defined as three indices (i, j, k) such that i < j < k, nums[i] < nums[j], and nums[k] < nums[j].
Difficulty: 🟢 Easy
Topics: Array
Solution
Problem Understanding
The problem asks us to find the minimum possible sum of a "mountain triplet" within a given array of integers. A mountain triplet is defined as three indices (i, j, k) such that i < j < k, nums[i] < nums[j], and nums[k] < nums[j]. Essentially, the middle element must be strictly larger than both its left and right neighbors, forming a peak. The input is an array of integers, with a length between 3 and 50, and integer values between 1 and 50. The expected output is either the minimum sum of a valid mountain triplet or -1 if no mountain exists.
Given the small constraints (nums.length <= 50), the problem is manageable without highly complex data structures. Edge cases include arrays that are strictly increasing or decreasing, arrays where all elements are equal, and arrays with multiple potential mountains where the minimal sum is non-obvious.
Approaches
Brute Force
A brute-force approach would involve iterating over all possible triplets (i, j, k) where i < j < k, checking whether they form a mountain, and keeping track of the minimum sum. This approach works because it explicitly considers every triplet, ensuring correctness. However, the number of triplets is combinatorial, specifically O(n^3), which is feasible for n = 50 but not efficient.
Optimal Approach
The key observation is that for each potential peak nums[j], we only need the smallest value to its left that is smaller than nums[j] and the smallest value to its right that is smaller than nums[j]. By iterating over the array and maintaining these minimums, we reduce the complexity from O(n^3) to O(n^2). For each index j, we scan all previous indices i < j to find a valid left candidate and all following indices k > j to find a valid right candidate, then compute the sum if both exist. This guarantees the minimal sum is captured.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n^3) | O(1) | Check every triplet (i, j, k) for the mountain property |
| Optimal | O(n^2) | O(1) | For each peak j, find smallest valid left and right values |
Algorithm Walkthrough
- Initialize a variable
min_sumtoinf. This will store the minimum sum of a valid mountain triplet. - Iterate over each index
jfrom1tolen(nums)-2, treatingnums[j]as the potential peak. - For each
j, initializeleft_mintoinf. Scan all indicesito the left ofj(0 <= i < j). Ifnums[i] < nums[j], updateleft_minifnums[i]is smaller than the currentleft_min. - Similarly, initialize
right_mintoinf. Scan all indiceskto the right ofj(j < k < n). Ifnums[k] < nums[j], updateright_minifnums[k]is smaller than the currentright_min. - If both
left_minandright_minare notinf, compute the sumleft_min + nums[j] + right_minand updatemin_sumif this sum is smaller than the currentmin_sum. - After iterating all potential peaks, return
min_sumif it has been updated, otherwise return-1if no mountain exists.
Why it works: For each peak candidate, we only need the minimal smaller numbers on both sides. By considering every potential peak, we guarantee that the absolute minimum sum is found.
Python Solution
from typing import List
class Solution:
def minimumSum(self, nums: List[int]) -> int:
n = len(nums)
min_sum = float('inf')
for j in range(1, n - 1):
left_min = float('inf')
right_min = float('inf')
for i in range(j):
if nums[i] < nums[j]:
left_min = min(left_min, nums[i])
for k in range(j + 1, n):
if nums[k] < nums[j]:
right_min = min(right_min, nums[k])
if left_min != float('inf') and right_min != float('inf'):
min_sum = min(min_sum, left_min + nums[j] + right_min)
return min_sum if min_sum != float('inf') else -1
The implementation follows the algorithm exactly. The outer loop selects the peak, and the two inner loops find the smallest valid left and right elements. The conditional ensures we only compute sums for valid mountains. If no valid mountain exists, min_sum remains inf, and we return -1.
Go Solution
import "math"
func minimumSum(nums []int) int {
n := len(nums)
minSum := math.MaxInt32
for j := 1; j < n-1; j++ {
leftMin := math.MaxInt32
rightMin := math.MaxInt32
for i := 0; i < j; i++ {
if nums[i] < nums[j] && nums[i] < leftMin {
leftMin = nums[i]
}
}
for k := j + 1; k < n; k++ {
if nums[k] < nums[j] && nums[k] < rightMin {
rightMin = nums[k]
}
}
if leftMin != math.MaxInt32 && rightMin != math.MaxInt32 {
sum := leftMin + nums[j] + rightMin
if sum < minSum {
minSum = sum
}
}
}
if minSum == math.MaxInt32 {
return -1
}
return minSum
}
Go differences: Instead of float('inf'), we use math.MaxInt32. Go arrays are slices, so we iterate with standard index ranges. Overflow is not a concern because the maximum possible sum is 50 + 50 + 50 = 150, well below int32 limits.
Worked Examples
Example 1: nums = [8,6,1,5,3]
- j = 1 (6): left < 6 → 8 (not valid), right < 6 → 1, 5, 3 → min 1, sum = 6 + 1 + 1? invalid, left not valid
- j = 2 (1): left < 1 → none, skip
- j = 3 (5): left < 5 → 1, right < 5 → 3, sum = 1 + 5 + 3 = 9 → update min_sum = 9
- j = 4 (3): left < 3 → 1, right < 3 → none, skip
Return 9.
Example 2: nums = [5,4,8,7,10,2]
- j = 2 (8): left < 8 → 5,4 → min 4, right < 8 → 7,10,2 → min 2, sum = 4+8+2=14
- j = 3 (7): left < 7 → 5,4 → min 4, right < 7 → 2 → sum = 4+7+2=13 → update min_sum
- j = 4 (10): left < 10 → 5,4,8,7 → min 4, right < 10 → 2 → sum = 4+10+2=16
- Return 13
Example 3: nums = [6,5,4,3,4,5]
- Scan all j: no valid mountain triplets found → return -1
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n^2) | Two nested loops for each peak j over the left and right sides |
| Space | O(1) | Only constant extra variables are used |
The algorithm scans the array repeatedly for each potential peak, but since n <= 50, O(n^2) is efficient. No extra data structures are required, keeping space minimal.
Test Cases
# Provided examples
assert Solution().minimumSum([8,6,1,5,3]) == 9
assert Solution().minimumSum([5,4,8,7,10,2]) == 13
assert Solution().minimumSum([6,5,4,3,4,5]) == -1
# Edge cases
assert Solution().minimumSum([1,2,3]) == -1 # strictly increasing, no mountain
assert Solution().minimumSum([3,2,1]) == -1 # strictly decreasing, no mountain
assert Solution().minimumSum([1,3,2]) == 6 # single mountain
assert Solution().minimumSum([50,1,50]) == 101 # peak in middle
assert Solution().minimumSum([1,50,1,2,49,2]) == 4+50+1 # multiple options, minimal sum chosen
| Test | Why |