When beginning competitive programming, problems that seem mathematically simple often contain hidden traps. HackerRank's Min-Max Sum challenge is a perfect example of this.

The problem asks us to take five positive integers and calculate the minimum and maximum sums possible by combining exactly four of them. While the arithmetic is basic, the core challenge lies in understanding how data types handle large numerical boundaries.

For instance, when input integers approach one billion, summing them exceeds standard 32-bit storage limits. To write a production-ready solution, we must avoid numerical overflow. In this tutorial, we will explore both functional Stream-based reduction and optimized single-pass loops to solve this safely in Java.

Illustration representing array processing and numeric calculations
Real-World Analogy: The Five Weights Balance

To visualize the underlying math, imagine you have five physical weights sitting on a table: 1g, 2g, 3g, 4g, and 5g. You are asked to choose exactly four of these weights and calculate their combined weight.

  • For the Minimum Sum: To obtain the lightest possible combination, you leave behind the single heaviest weight (5g). The remaining weights sum to 1 + 2 + 3 + 4 = 10g.
  • For the Maximum Sum: To obtain the heaviest possible combination, you leave behind the single lightest weight (1g). The remaining weights sum to 2 + 3 + 4 + 5 = 14g.

Instead of calculating every permutation of four weights, the most efficient method is to find the total sum of all five weights. From there:

  • Minimum Sum = Total Sum - Maximum Element
  • Maximum Sum = Total Sum - Minimum Element
This logic requires finding only the min, max, and total sum of the dataset in a single pass.

Algorithmic Solutions & Integer Overflow

We can implement this logic in Java using two different coding styles:

  1. Functional Stream Reduction: We convert our list into a stream and apply .reduce() operators to calculate the minimum value, maximum value, and overall sum. This declarative style is highly readable.
  2. Greedy Single-Loop Pass: We loop through the list once, updating our running minValue and maxValue checkers, while accumulating a running sum.

Warning: The Integer Overflow Trap!

A standard 32-bit Java int supports values up to 2,147,483,647. If the five input values are large (such as 1,000,000,000), the sum becomes 5,000,000,000, which overflows the integer range and yields incorrect negative numbers.

To prevent this truncation, we must declare the sum using a 64-bit long data type, which supports values up to 9,223,372,036,854,775,807. Using long variables guarantees correct calculations.

Step-by-Step Scenario Trace

Let's trace a sample array: arr = [1, 3, 5, 7, 9]:

  • Step 1 (Initialization): We set minValue = 1, maxValue = 1, totalSum = 0.
  • Step 2 (Looping & Accumulation):
    • For 1: totalSum = 1. Trackers remain unchanged.
    • For 3: totalSum = 4. Since 3 > maxValue, maxValue = 3.
    • For 5: totalSum = 9. Since 5 > maxValue, maxValue = 5.
    • For 7: totalSum = 16. Since 7 > maxValue, maxValue = 7.
    • For 9: totalSum = 25. Since 9 > maxValue, maxValue = 9.
  • Step 3 (Final Calculation):
    • Min Sum = 25 - 9 = 16 (sum of 1 + 3 + 5 + 7).
    • Max Sum = 25 - 1 = 24 (sum of 3 + 5 + 7 + 9).
Our console prints 16 24.

Java Implementation Code

Below is the complete solution including input reading:

package io.practise.hackerrank;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
 
public class MinMaxSum {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
 
        List<Integer> arr = Stream.of(bufferedReader.readLine().replaceAll("\\s+$", "").split(" "))
                .map(Integer::parseInt)
                .collect(toList());
 
        miniMaxSum(arr);
        bufferedReader.close();
    }
 
    public static void miniMaxSum(List<Integer> arr) {
        long minValue = arr.get(0);
        long maxValue = arr.get(0);
        long totalSum = 0;
 
        for (int val : arr) {
            totalSum += val; // Prevents overflow via long arithmetic
            if (val < minValue) minValue = val;
            if (val > maxValue) maxValue = val;
        }
 
        System.out.println((totalSum - maxValue) + " " + (totalSum - minValue));
    }
}

Conclusion & Complexity Analysis

This greedy algorithm runs in O(N) linear time complexity (where N is the number of elements) and uses O(1) constant space. By utilizing the mathematical relationship between the total sum and extreme values, we solve the challenge in a single pass while using proper type declarations to avoid integer overflows.