Facebook Pixel

2221. Find Triangular Sum of an Array

Problem Description

You are given an array of single digits (0-9). Your task is to find the triangular sum of this array through a specific process.

The process works like this:

Starting with your array nums, you repeatedly create a new array that is one element shorter by adding adjacent pairs and taking the result modulo 10. You continue this process until only one element remains.

Here's how each iteration works:

  1. If the array has only 1 element, stop - that's your answer
  2. Otherwise, create a new array with length n-1 (one element shorter)
  3. For each position i in the new array, set newNums[i] = (nums[i] + nums[i+1]) % 10
  4. Replace the original array with this new array and repeat

For example, if you start with [1, 2, 3, 4, 5]:

  • Round 1: [(1+2)%10, (2+3)%10, (3+4)%10, (4+5)%10] = [3, 5, 7, 9]
  • Round 2: [(3+5)%10, (5+7)%10, (7+9)%10] = [8, 2, 6]
  • Round 3: [(8+2)%10, (2+6)%10] = [0, 8]
  • Round 4: [(0+8)%10] = [8]
  • Result: 8

The solution uses a simple simulation approach with nested loops. The outer loop controls how many rounds to perform (from n-1 down to 1), and the inner loop calculates the new values for each position by adding adjacent elements and taking modulo 10. The array is updated in-place to save space, and after all rounds, nums[0] contains the final triangular sum.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The problem describes a process that naturally forms a triangle pattern. If we visualize each round of operations, we can see that we're building a pyramid from bottom to top, where each level has one fewer element than the level below it.

Think of it like this: we start with n elements at the bottom, then n-1 elements in the next level up, then n-2, and so on, until we reach the single element at the top. This is exactly like Pascal's triangle, but with modulo 10 arithmetic.

The key insight is that we don't need to store all intermediate arrays - we can reuse the same array and update it in-place. Since we're always reading two adjacent elements nums[i] and nums[i+1] to compute the new value at position i, we can safely overwrite nums[i] with the result because we won't need the original value again in that round.

The natural way to implement this is with two nested loops:

  • The outer loop controls how many elements we're processing in each round (starting from n-1 and decreasing to 1)
  • The inner loop performs the actual calculation for each position

Why does the outer loop go from len(nums) - 1 down to 1? Because in each round, we reduce the effective size of our array by 1. In the first round, we process n-1 pairs to get n-1 results. In the second round, we process n-2 pairs, and so on.

The modulo 10 operation ensures our values stay as single digits throughout the process, which is both a requirement of the problem and prevents integer overflow issues.

Learn more about Math and Combinatorics patterns.

Solution Approach

The solution uses a simulation approach that directly implements the process described in the problem. Here's how the implementation works:

Algorithm Structure: The solution uses two nested loops to progressively reduce the array size until only one element remains.

Outer Loop: for k in range(len(nums) - 1, 0, -1)

  • This loop controls the number of elements we process in each round
  • It starts from len(nums) - 1 and decrements down to 1
  • The variable k represents how many elements we'll have after the current round of processing
  • We need exactly n-1 rounds to reduce an array of size n to size 1

Inner Loop: for i in range(k)

  • This loop performs the actual calculation for each position
  • It iterates from index 0 to k-1, computing the new value for each position
  • For each index i, it calculates: nums[i] = (nums[i] + nums[i + 1]) % 10

In-Place Update Strategy: The key optimization is updating the array in-place. When we compute nums[i] = (nums[i] + nums[i+1]) % 10, we:

  1. Read the current value at nums[i] and nums[i+1]
  2. Add them together and apply modulo 10
  3. Store the result back in nums[i]

This works because once we've used nums[i] to compute the new value, we don't need the original value anymore in that round. The next iteration will use nums[i+1] and nums[i+2], so overwriting nums[i] is safe.

Space Complexity: O(1) - We modify the input array in-place without using extra space Time Complexity: O(n²) - We have nested loops where the outer loop runs n-1 times and the inner loop runs k times (where k decreases from n-1 to 1), giving us a total of (n-1) + (n-2) + ... + 1 = n*(n-1)/2` operations

After all rounds complete, nums[0] contains the final triangular sum, which is returned as the result.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with the array [2, 6, 1]:

Initial Setup:

  • nums = [2, 6, 1]
  • Array length n = 3
  • We need n-1 = 2 rounds to reduce to a single element

Round 1: k = 2

  • Outer loop: k = 2 (we'll process 2 pairs to get 2 elements)
  • Inner loop iterations:
    • i = 0: nums[0] = (nums[0] + nums[1]) % 10 = (2 + 6) % 10 = 8
      • Array becomes: [8, 6, 1]
    • i = 1: nums[1] = (nums[1] + nums[2]) % 10 = (6 + 1) % 10 = 7
      • Array becomes: [8, 7, 1]
  • After Round 1: We now logically have [8, 7] (ignore index 2)

Round 2: k = 1

  • Outer loop: k = 1 (we'll process 1 pair to get 1 element)
  • Inner loop iterations:
    • i = 0: nums[0] = (nums[0] + nums[1]) % 10 = (8 + 7) % 10 = 15 % 10 = 5
      • Array becomes: [5, 7, 1]
  • After Round 2: We now have [5] at index 0

Result: nums[0] = 5

The triangular pattern visualization:

    5      <- Final result
   8 7     <- After round 1
  2 6 1    <- Original array

Notice how each element in a row is the sum (mod 10) of the two elements directly below it, forming a triangular structure. The in-place update strategy means we reuse the same array throughout, only caring about the first k elements in each round.

Solution Implementation

1class Solution:
2    def triangularSum(self, nums: List[int]) -> int:
3        """
4        Calculate the triangular sum of a list of numbers.
5      
6        The triangular sum is computed by repeatedly summing adjacent pairs
7        and reducing the array size by 1 each iteration until one element remains.
8        Each sum is taken modulo 10 to keep single digits.
9      
10        Args:
11            nums: List of integers to compute triangular sum
12          
13        Returns:
14            The final single digit result after all reductions
15        """
16        # Iterate from the last index down to 1
17        # Each iteration reduces the effective array size by 1
18        for current_length in range(len(nums) - 1, 0, -1):
19            # For each position in the current effective array
20            # Replace each element with sum of itself and next element
21            for i in range(current_length):
22                # Add current and next element, take modulo 10 for single digit
23                nums[i] = (nums[i] + nums[i + 1]) % 10
24      
25        # Return the final remaining element
26        return nums[0]
27
1class Solution {
2    public int triangularSum(int[] nums) {
3        // Process the array layer by layer, reducing size by 1 each iteration
4        // Start from the last index and work towards the beginning
5        for (int currentLength = nums.length - 1; currentLength > 0; currentLength--) {
6            // For each position in the current layer, calculate the sum of adjacent elements
7            for (int index = 0; index < currentLength; index++) {
8                // Replace current element with sum of itself and next element, modulo 10
9                // This simulates the triangular sum operation where each new value
10                // is the sum of two adjacent values from the previous row
11                nums[index] = (nums[index] + nums[index + 1]) % 10;
12            }
13        }
14      
15        // After all iterations, the first element contains the final triangular sum
16        return nums[0];
17    }
18}
19
1class Solution {
2public:
3    int triangularSum(vector<int>& nums) {
4        // Iterate through levels of the triangle from bottom to top
5        // k represents the current size of the array we're processing
6        for (int level_size = nums.size() - 1; level_size > 0; --level_size) {
7            // For each level, calculate new values by summing adjacent pairs
8            // Store the result in-place, overwriting the left element
9            for (int i = 0; i < level_size; ++i) {
10                // Add current element with next element and take modulo 10
11                // This simulates the triangular sum operation
12                nums[i] = (nums[i] + nums[i + 1]) % 10;
13            }
14        }
15      
16        // After all iterations, the result is stored in the first element
17        return nums[0];
18    }
19};
20
1/**
2 * Calculates the triangular sum of an array of numbers.
3 * The triangular sum is computed by repeatedly combining adjacent elements
4 * until a single value remains.
5 * 
6 * @param nums - Array of numbers to process
7 * @returns The final triangular sum value
8 */
9function triangularSum(nums: number[]): number {
10    // Iterate from the last index down to 1
11    // Each iteration reduces the effective array size by 1
12    for (let currentLength = nums.length - 1; currentLength > 0; currentLength--) {
13        // Process adjacent pairs in the current range
14        for (let index = 0; index < currentLength; index++) {
15            // Add current element with next element and take modulo 10
16            // Store the result in place at the current position
17            nums[index] = (nums[index] + nums[index + 1]) % 10;
18        }
19    }
20  
21    // Return the final computed value at the first position
22    return nums[0];
23}
24

Time and Space Complexity

Time Complexity: O(n²), where n is the length of the array nums.

The algorithm uses two nested loops:

  • The outer loop runs from len(nums) - 1 down to 1, executing n - 1 iterations
  • For each iteration k of the outer loop, the inner loop runs k times
  • Total operations: (n-1) + (n-2) + ... + 2 + 1 = n(n-1)/2
  • This simplifies to O(n²)

Space Complexity: O(1)

The algorithm modifies the input array in-place without using any additional data structures. Only a constant amount of extra space is used for the loop variables k and i, regardless of the input size.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Index Out of Bounds Error

One of the most common mistakes is incorrectly managing the loop boundaries, particularly in the inner loop. Developers might accidentally access nums[i+1] when i is already at the last valid position.

Incorrect Implementation:

# Wrong: This will cause index out of bounds
for k in range(len(nums) - 1, 0, -1):
    for i in range(k + 1):  # ERROR: should be range(k)
        nums[i] = (nums[i] + nums[i + 1]) % 10

Why it fails: When i = k, trying to access nums[i+1] means accessing nums[k+1], which is beyond the current working range.

Solution: Always ensure the inner loop runs from 0 to k-1 (using range(k)), not 0 to k.

2. Forgetting the Modulo Operation

Another pitfall is forgetting to apply % 10 to keep results as single digits, which is a core requirement of the problem.

Incorrect Implementation:

for k in range(len(nums) - 1, 0, -1):
    for i in range(k):
        nums[i] = nums[i] + nums[i + 1]  # Missing % 10

Why it fails: Without modulo 10, values can grow beyond single digits, producing incorrect results. For example, [8, 7] would become [15] instead of [5].

Solution: Always apply % 10 to the sum: nums[i] = (nums[i] + nums[i + 1]) % 10

3. Creating New Arrays Instead of In-Place Updates

Some might create a new array for each iteration, which works but is inefficient and more error-prone.

Inefficient Implementation:

while len(nums) > 1:
    new_nums = []
    for i in range(len(nums) - 1):
        new_nums.append((nums[i] + nums[i + 1]) % 10)
    nums = new_nums  # Creates new array each time
return nums[0]

Why it's problematic: This uses O(n²) extra space and requires careful array management. It's also easier to make mistakes with array assignment and boundary conditions.

Solution: Use the in-place approach shown in the original solution to save space and simplify logic.

4. Edge Case: Single Element Array

Failing to handle arrays with only one element can cause issues.

Problematic Approach:

# This works but may confuse some developers
for k in range(len(nums) - 1, 0, -1):  # When len(nums)=1, range(0, 0, -1) is empty
    for i in range(k):
        nums[i] = (nums[i] + nums[i + 1]) % 10

Why it might confuse: When nums has only 1 element, range(0, 0, -1) produces an empty sequence, so the loops don't execute at all. While this correctly returns nums[0], it might not be immediately obvious.

Solution: The original implementation handles this naturally since an empty range means no iterations occur, and nums[0] is returned directly. However, you could add an explicit check for clarity:

if len(nums) == 1:
    return nums[0]
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Given a sorted array of integers and an integer called target, find the element that equals to the target and return its index. Select the correct code that fills the ___ in the given code snippet.

1def binary_search(arr, target):
2    left, right = 0, len(arr) - 1
3    while left ___ right:
4        mid = (left + right) // 2
5        if arr[mid] == target:
6            return mid
7        if arr[mid] < target:
8            ___ = mid + 1
9        else:
10            ___ = mid - 1
11    return -1
12
1public static int binarySearch(int[] arr, int target) {
2    int left = 0;
3    int right = arr.length - 1;
4
5    while (left ___ right) {
6        int mid = left + (right - left) / 2;
7        if (arr[mid] == target) return mid;
8        if (arr[mid] < target) {
9            ___ = mid + 1;
10        } else {
11            ___ = mid - 1;
12        }
13    }
14    return -1;
15}
16
1function binarySearch(arr, target) {
2    let left = 0;
3    let right = arr.length - 1;
4
5    while (left ___ right) {
6        let mid = left + Math.trunc((right - left) / 2);
7        if (arr[mid] == target) return mid;
8        if (arr[mid] < target) {
9            ___ = mid + 1;
10        } else {
11            ___ = mid - 1;
12        }
13    }
14    return -1;
15}
16

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More