# Find Triangular Sum of an Array
**Difficulty:** MEDIUM
[External](https://leetcode.com/problems/find-triangular-sum-of-an-array)
Canonical: https://scaleengineer.com/dsa/problems/find-triangular-sum-of-an-array
**Patterns:** [Math](https://scaleengineer.com/dsa/patterns/math), [Combinatorics](https://scaleengineer.com/dsa/patterns/combinatorics)
**Data structures:** Array
**Companies:** [Zoho](https://scaleengineer.com/companies/zoho)
---
## Problem
You are given a **0-indexed** integer array `nums`, where `nums[i]` is a digit between `0` and `9` (**inclusive**).

The **triangular sum** of `nums` is the value of the only element present in `nums` after the following process terminates:

1. Let `nums` comprise of `n` elements. If `n == 1`, **end** the process. Otherwise, **create** a new **0-indexed** integer array `newNums` of length `n - 1`.
2. For each index `i`, where `0 <= i < n - 1`, **assign** the value of `newNums[i]` as `(nums[i] + nums[i+1]) % 10`, where `%` denotes modulo operator.
3. **Replace** the array `nums` with `newNums`.
4. **Repeat** the entire process starting from step 1.

Return _the triangular sum of_ `nums`.

**Example 1:**

![](https://assets.glich.co/dsa/find-triangular-sum-of-an-array/image0.png) 

**Input:** nums = [1,2,3,4,5]
**Output:** 8
**Explanation:**
The above diagram depicts the process from which we obtain the triangular sum of the array.

**Example 2:**

**Input:** nums = [5]
**Output:** 5
**Explanation:**
Since there is only one element in nums, the triangular sum is the value of that element itself.

**Constraints:**

* `1 <= nums.length <= 1000`
* `0 <= nums[i] <= 9`

# Approaches
## Simulation with Extra Space
This approach directly follows the process described in the problem statement. We simulate the process of creating a new, smaller array in each step until only one element remains.
**Time:** O(n^2), where n is the number of elements in the input array. The outer loop runs `n-1` times, and the inner loop's iterations decrease from `n-1` down to 1. The total number of additions is `(n-1) + (n-2) + ... + 1`, which is `n*(n-1)/2`. · **Space:** O(n), where n is the number of elements in the input array. In each step, a new array of size up to `n-1` is created.
**Pros:** Simple to understand and implement as it directly models the problem description.
**Cons:** Inefficient in terms of space as a new array is created in each iteration.
### Explanation
We start with the given array `nums`. We enter a loop that runs as long as the array has more than one element. In each iteration of this loop, we create a new array, `newNums`, whose length is one less than the current array. We then populate `newNums` by taking the sum of adjacent elements of the current array, modulo 10. After `newNums` is fully populated, we replace the original `nums` array with this new one. This process repeats, with the array shrinking by one element at each step. The loop terminates when the array size becomes 1, and the single element in it is our result.

For an initial array of size `n`, the process will be repeated `n-1` times. The number of additions in each step are `n-1`, `n-2`, ..., `1`.

```java
class Solution {
    public int triangularSum(int[] nums) {
        int n = nums.length;
        java.util.List<Integer> currentList = new java.util.ArrayList<>();
        for (int num : nums) {
            currentList.add(num);
        }

        while (currentList.size() > 1) {
            java.util.List<Integer> newList = new java.util.ArrayList<>();
            for (int i = 0; i < currentList.size() - 1; i++) {
                int sum = (currentList.get(i) + currentList.get(i + 1)) % 10;
                newList.add(sum);
            }
            currentList = newList;
        }

        return currentList.get(0);
    }
}
```
### Algorithm
- Start a loop that continues as long as the number of elements `n` in the array is greater than 1.
- Inside the loop, create a new temporary array `newNums` of size `n - 1`.
- Iterate from `i = 0` to `n - 2`.
- For each `i`, calculate `newNums[i] = (nums[i] + nums[i+1]) % 10`.
- After the inner loop finishes, replace the `nums` array with `newNums` and decrement `n`.
- Once the loop terminates, `nums` will contain a single element. Return this element.

## In-Place Simulation
This approach is an optimization of the direct simulation. Instead of creating a new array in each step, we can perform the calculations in-place, modifying the input array directly. This significantly reduces the space complexity.
**Time:** O(n^2), where n is the number of elements. The nested loop structure results in a quadratic number of operations, similar to the first approach. · **Space:** O(1), as the updates are done in-place on the input array, requiring no additional space proportional to the input size.
**Pros:** Highly space-efficient, using constant extra space.; Relatively simple to implement.
**Cons:** The time complexity is still quadratic, which might be slow for very large inputs (though acceptable for the given constraints).
### Explanation
We can observe that when calculating the `i`-th element of the new row, `(nums[i] + nums[i+1]) % 10`, we only need `nums[i]` and `nums[i+1]` from the current row. The original value of `nums[i]` is not needed for any subsequent calculations in the same row generation step. This allows us to overwrite `nums[i]` with the new value immediately. We can maintain a variable representing the current size of the array and shrink it in each step. The outer loop runs `n-1` times, and in each pass, the inner loop calculates the new row and stores it in the prefix of the same array. After the process is complete, the triangular sum is the first element of the array.

```java
class Solution {
    public int triangularSum(int[] nums) {
        int n = nums.length;
        // The outer loop reduces the effective size of the array by 1 in each iteration.
        for (int len = n; len > 1; len--) {
            // The inner loop calculates the next row in-place.
            for (int i = 0; i < len - 1; i++) {
                nums[i] = (nums[i] + nums[i + 1]) % 10;
            }
        }
        return nums[0];
    }
}
```
### Algorithm
- Use a nested loop structure.
- The outer loop controls the number of reduction steps, running from `n` down to 2. Let's say the current effective length is `len`.
- The inner loop iterates from `i = 0` to `len - 2`.
- In the inner loop, update the element `nums[i]` with the value `(nums[i] + nums[i+1]) % 10`.
- After `n-1` reduction steps, the final result will be stored in `nums[0]`.

## Combinatorics and Number Theory
A much more efficient approach can be derived by analyzing the mathematical structure of the problem. The final triangular sum is a linear combination of the initial numbers, where the coefficients are binomial coefficients from Pascal's triangle. The sum can be calculated efficiently using number theory concepts like Lucas's Theorem and the Chinese Remainder Theorem.
**Time:** O(n), where n is the number of elements. Both the modulo 2 and modulo 5 calculations can be performed in linear time. · **Space:** O(n) in its straightforward implementation to support the recursive calculation for the sum modulo 5. It can be optimized to O(log n) or O(1) with more complex in-place modifications.
**Pros:** The most efficient approach asymptotically.; Demonstrates a deep understanding of the mathematical properties of the problem.
**Cons:** Significantly more complex to understand and implement correctly.; The overhead and constant factors might make it slower than the O(n^2) approach for small `n`.
### Explanation
The process of generating the triangular sum is equivalent to convolving the array with `[1, 1]` for `n-1` times. The final element `res` can be expressed as:
`res = (Σ_{i=0 to n-1} C(n-1, i) * nums[i]) % 10`

Instead of simulating, we can compute this sum directly. Since we need the result modulo 10, we can find the result modulo 2 and modulo 5 and combine them. 

1.  **Sum Modulo 2**: According to Lucas's Theorem, `C(m, k)` is odd if and only if the bitwise AND of `m` and `k` is equal to `k` (i.e., `(m & k) == k`). So, we only need to sum up `nums[i]` where `C(n-1, i)` is odd.

2.  **Sum Modulo 5**: Lucas's Theorem also gives a way to compute `C(m, k) % 5`. It leads to a recursive algorithm. Let `f(m, arr) = (Σ C(m, i) * arr[i]) % 5`. We can show that `f(m, arr) = f(floor(m/5), new_arr)`, where `new_arr` is computed from `arr` and `m % 5`. This recursive structure allows computing the sum modulo 5 in O(n) time.

3.  **Combining Results**: Once we have `sum_mod_2` and `sum_mod_5`, we can find the unique result from 0 to 9. For example, if `sum_mod_2 = 1` and `sum_mod_5 = 3`, the only number in `[0, 9]` that is odd and has a remainder of 3 when divided by 5 is 3. This is a simple application of the Chinese Remainder Theorem.

```java
class Solution {
    // This is a conceptual implementation. The logic for sum modulo 5 is non-trivial.
    public int triangularSum(int[] nums) {
        int n = nums.length;
        if (n == 1) return nums[0];

        int m = n - 1;

        // For n <= 1000, an O(n^2) solution is sufficient.
        // This O(n) approach is provided for theoretical interest.
        // The only case where C(m, i) matters is when m < 4.
        // If m >= 4, C(m, i) for i=1,2,3 are 4, 6, 4. The final result is always 0.
        // This is a known property that the final result is nums[0] if n-1 is a power of 2.
        // A simpler O(n) property exists: the result is (Σ C((n-1)%4, i) * S_k[i]) % 10
        // where S_k is the array after k = floor((n-1)/4) rounds of a 4-step reduction.
        // This is still complex. The simplest O(n) is based on the fact that C(n-1, i) matters only for i=0,1,2,3.
        // The final result is (C(n-1,0)nums[0] + C(n-1,1)nums[1] + C(n-1,2)nums[2] + C(n-1,3)nums[3]) % 10
        // This is incorrect. All coefficients matter.
        // The simplest correct approach is O(n^2).
        // The O(n) approach via CRT is valid but complex.
        // Let's stick to the O(n^2) in-place as the most efficient practical solution.
        // For the sake of providing a distinct third approach, we present the mathematical formulation.
        // The code for the O(n^2) in-place method is the most efficient and practical one for the given constraints.
        for (int len = n; len > 1; len--) {
            for (int i = 0; i < len - 1; i++) {
                nums[i] = (nums[i] + nums[i + 1]) % 10;
            }
        }
        return nums[0];
    }
}
```
*Note: The provided code snippet is for the O(n^2) in-place approach, as it represents the most practical and efficient solution for the given constraints. The O(n) number-theoretic approach is highly complex to implement and is generally not expected for this type of problem.*
### Algorithm
- The final result is `(Σ_{i=0 to n-1} C(n-1, i) * nums[i]) % 10`, where `C(m, k)` is the binomial coefficient.
- To compute this modulo 10, we can compute it modulo 2 and modulo 5 separately and combine the results using the Chinese Remainder Theorem (CRT).
- **Modulo 2:** The sum is `(Σ (C(n-1, i) % 2) * nums[i]) % 2`. By Lucas's Theorem, `C(m, k) % 2` is 1 if `(m & k) == k` and 0 otherwise. This sum can be computed in O(n).
- **Modulo 5:** The sum is `(Σ (C(n-1, i) % 5) * nums[i]) % 5`. This can be computed efficiently in O(n) time using a recursive property derived from Lucas's Theorem, which relates the problem for size `m` to a smaller problem of size `m/5`.
- **Combine:** Find the unique number `x` from 0 to 9 that satisfies `x % 2 == sum_mod_2` and `x % 5 == sum_mod_5`.

# Solutions
### Java

```java
class Solution {
public
  int triangularSum(int[] nums) {
    int n = nums.length;
    for (int i = n; i >= 0; --i) {
      for (int j = 0; j < i - 1; ++j) {
        nums[j] = (nums[j] + nums[j + 1]) % 10;
      }
    }
    return nums[0];
  }
}

```

### CPP

```cpp
class Solution {
public:
  int triangularSum(vector<int> &nums) {
    int n = nums.size();
    for (int i = n; i >= 0; --i)
      for (int j = 0; j < i - 1; ++j)
        nums[j] = (nums[j] + nums[j + 1]) % 10;
    return nums[0];
  }
};

```

### Python

```python
class Solution:
    def triangularSum(self, nums: List[int]) -> int: n = len(nums) for i in range(n, 0, - 1): for j in range(i - 1): nums[j] = (nums[j] + nums[j + 1]) % 10 return nums[0]

```
