triangular matrix
index numbers
algorithm design
matrix coefficients
mathematical computation

algorithm for index numbers of triangular matrix coefficients

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

When a matrix is triangular, half of its entries are known to be zero, so storing the full square matrix wastes space. A common optimization is packed storage, where only the meaningful coefficients are placed in a one-dimensional array. The core problem then becomes index mapping: given matrix coordinates, what is the position in that packed array?

Choose a Storage Order First

There is no single universal formula until you fix the storage convention. Two decisions matter:

  • upper or lower triangular matrix
  • row-major or column-major packed order

Without that, two correct implementations can produce different linear indices for the same matrix coordinate.

This article uses zero-based indexing and row-major packed storage.

Lower Triangular Matrix Formula

For a lower triangular matrix, valid positions satisfy i >= j. In row-major packed storage, row 0 contributes one stored element, row 1 contributes two, and so on.

The number of stored elements before row i is:

  • 'i * (i + 1) / 2'

So the packed index is:

  • 'k = i * (i + 1) / 2 + j'

A Python implementation:

python
1def lower_triangular_index(i, j):
2    if j > i:
3        raise ValueError("Position is outside the stored lower triangle")
4    return i * (i + 1) // 2 + j
5
6
7for i in range(4):
8    for j in range(i + 1):
9        print((i, j), lower_triangular_index(i, j))

For a 4 x 4 lower triangular matrix, this maps the stored coefficients to indices 0 through 9.

Upper Triangular Matrix Formula

For an upper triangular matrix, valid positions satisfy j >= i. In row-major packed storage, row 0 contributes n stored elements, row 1 contributes n - 1, and so on.

The number of elements before row i is:

  • 'i * n - i * (i - 1) / 2'

So the packed index becomes:

  • 'k = i * n - i * (i - 1) / 2 + (j - i)'

Here is a runnable version:

python
1def upper_triangular_index(n, i, j):
2    if j < i:
3        raise ValueError("Position is outside the stored upper triangle")
4    return i * n - i * (i - 1) // 2 + (j - i)
5
6
7n = 4
8for i in range(n):
9    for j in range(i, n):
10        print((i, j), upper_triangular_index(n, i, j))

This formula depends on the full matrix size n, which is why it takes one extra parameter.

Why Triangular Numbers Appear

The formulas use triangular-number counts because the number of stored elements grows or shrinks by one per row.

For the lower triangle, the prefix lengths are:

  • '1'
  • '1 + 2'
  • '1 + 2 + 3'

That cumulative pattern is exactly why the i * (i + 1) / 2 term appears.

Verify the Mapping with Packed Storage

Once you have the formula, storing and reading values becomes straightforward.

python
1def build_lower_storage(matrix):
2    packed = []
3    for i, row in enumerate(matrix):
4        for j in range(i + 1):
5            packed.append(row[j])
6    return packed
7
8
9matrix = [
10    [1, 0, 0],
11    [2, 3, 0],
12    [4, 5, 6],
13]
14
15packed = build_lower_storage(matrix)
16print(packed)
17print(packed[lower_triangular_index(2, 1)])

The index formula lets you access packed coefficients without rebuilding the square matrix.

Common Pitfalls

  • Forgetting to define the storage order before deriving the formula.
  • Mixing zero-based and one-based indexing.
  • Applying a lower-triangle formula to upper-triangle storage, or the reverse.
  • Ignoring invalid coordinates outside the stored triangle.
  • Recomputing the full matrix when packed access would be enough.

Summary

  • Triangular matrices are often stored in packed one-dimensional form to save space.
  • The index formula depends on upper versus lower storage and on row-major versus column-major order.
  • For zero-based lower-triangular row-major storage, use i * (i + 1) / 2 + j.
  • For zero-based upper-triangular row-major storage, use i * n - i * (i - 1) / 2 + (j - i).
  • Define the layout first, then derive or implement the matching formula.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.