Lower Triangular Matrix Check: Programs in C, Java, Python
A square matrix is lower triangular when all entries above the main diagonal are zero. Programs in C, C++, Java, and Python with traced example and complexity analysis.
A square matrix is lower triangular when every element above the main diagonal is zero; any non-zero value above that line immediately disqualifies it.
What Makes a Matrix Lower Triangular
The main diagonal of an n×n matrix runs from position (0, 0) to position (n-1, n-1). A matrix is lower triangular when every element whose column index is strictly greater than its row index equals zero. The elements on the diagonal and below it are unconstrained.
For a 3×3 matrix, the positions that must be zero are the ones in the upper-right triangle:
| Col 0 | Col 1 | Col 2 | |
|---|---|---|---|
| Row 0 | any | must be 0 | must be 0 |
| Row 1 | any | any | must be 0 |
| Row 2 | any | any | any |
A concrete example that passes the test:
| Col 0 | Col 1 | Col 2 | |
|---|---|---|---|
| Row 0 | 3 | 0 | 0 |
| Row 1 | 7 | 5 | 0 |
| Row 2 | 2 | 8 | 4 |
Every entry above the diagonal is 0. The diagonal values (3, 5, 4) and the sub-diagonal values (7, 2, 8) are unrestricted.
An example that fails, because the element at row 0, column 1 equals 6:
| Col 0 | Col 1 | Col 2 | |
|---|---|---|---|
| Row 0 | 3 | 6 | 0 |
| Row 1 | 7 | 5 | 0 |
| Row 2 | 2 | 8 | 4 |
One non-zero above the diagonal is enough to fail. The rest of the matrix is irrelevant once that violation is found.
According to the Wikipedia entry on triangular matrices, lower triangular matrices appear in numerical linear algebra primarily as one factor in LU decomposition, where a matrix is expressed as the product of a lower and an upper triangular matrix. That context is graduate-level; the placement-test context is simply recognising the pattern and writing the detection loop.
The Algorithm: Scanning the Upper Triangle
The algorithm examines only positions above the diagonal. Diagonal positions and sub-diagonal positions need no inspection.
Steps:
- Accept the order n of the square matrix.
- Read all n×n elements into the matrix.
- For row i from 0 to n-1:
- For column j from i+1 to n-1 (one step right of the diagonal):
- If mat[i][j] is not equal to 0, the matrix is not lower triangular. Stop.
- For column j from i+1 to n-1 (one step right of the diagonal):
- If no violation was found, the matrix is lower triangular.
The inner loop starts at j = i+1, not at j = 0. Starting at j = 0 would waste comparisons on the diagonal element (j = i) and the sub-diagonal elements (j less than i), neither of which affects the verdict. Skipping those positions keeps the loop clean and makes the intent explicit in the code.
The early exit on the first non-zero element matters for performance on large matrices where a violation occurs near the start. The worst case (a genuinely lower triangular matrix or a violation near the bottom-right) still requires scanning all n(n-1)/2 upper-triangle positions.
Programs to Check for Lower Triangular
All four implementations use the same two-loop structure. The language differences are syntactic.
C Program
#include <stdio.h>
int isLowerTriangular(int mat[][10], int n) {
int i, j;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (mat[i][j] != 0)
return 0;
}
}
return 1;
}
int main() {
int n, i, j;
printf("Enter the order of the square matrix: ");
scanf("%d", &n);
int mat[10][10];
printf("Enter the matrix elements:\n");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &mat[i][j]);
if (isLowerTriangular(mat, n))
printf("Lower triangular matrix\n");
else
printf("Not a lower triangular matrix\n");
return 0;
}
C++ Program
#include <iostream>
using namespace std;
bool isLowerTriangular(int mat[][10], int n) {
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (mat[i][j] != 0)
return false;
return true;
}
int main() {
int n;
cout << "Enter the order of the square matrix: ";
cin >> n;
int mat[10][10];
cout << "Enter the matrix elements:\n";
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> mat[i][j];
if (isLowerTriangular(mat, n))
cout << "Lower triangular matrix" << endl;
else
cout << "Not a lower triangular matrix" << endl;
return 0;
}
Java Program
import java.util.Scanner;
public class LowerTriangular {
static boolean isLowerTriangular(int[][] mat, int n) {
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (mat[i][j] != 0)
return false;
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter the order of the square matrix: ");
int n = sc.nextInt();
int[][] mat = new int[n][n];
System.out.println("Enter the matrix elements:");
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
mat[i][j] = sc.nextInt();
if (isLowerTriangular(mat, n))
System.out.println("Lower triangular matrix");
else
System.out.println("Not a lower triangular matrix");
}
}
Python Program
def is_lower_triangular(matrix, n):
for i in range(n):
for j in range(i + 1, n):
if matrix[i][j] != 0:
return False
return True
n = int(input("Enter the order of the square matrix: "))
matrix = []
print("Enter the matrix elements row by row:")
for i in range(n):
row = list(map(int, input().split()))
matrix.append(row)
if is_lower_triangular(matrix, n):
print("Lower triangular matrix")
else:
print("Not a lower triangular matrix")
The Python version uses range(i + 1, n) to generate column indices starting one position right of the diagonal. When matrix[i][j] != 0 is found, the function returns False immediately. No flag variable is needed because a return inside a nested loop exits the function entirely, unlike a break, which exits only the innermost loop.
Traced Example: Verifying a 3×3 Matrix Step-by-Step
Consider this 3×3 matrix:
mat = [[4, 0, 0],
[3, 7, 0],
[1, 5, 9]]
The upper-triangle positions to check are (row 0, col 1), (row 0, col 2), and (row 1, col 2). Positions on or below the diagonal are skipped.
Trace of the detection function:
- i = 0, j = 1: mat[0][1] = 0. Passes.
- i = 0, j = 2: mat[0][2] = 0. Passes.
- i = 1, j = 2: mat[1][2] = 0. Passes.
- i = 2: inner loop runs from j = 3 to j = 2, which is empty. Skipped.
- All positions checked. Output: “Lower triangular matrix.”
Now change mat[1][2] from 0 to 6:
mat = [[4, 0, 0],
[3, 7, 6],
[1, 5, 9]]
Trace:
- i = 0, j = 1: mat[0][1] = 0. Passes.
- i = 0, j = 2: mat[0][2] = 0. Passes.
- i = 1, j = 2: mat[1][2] = 6. Non-zero above the diagonal. Output: “Not a lower triangular matrix.” Function returns immediately.
The third check finds the violation without inspecting any sub-diagonal positions, confirming the early exit saves work.
Time and Space Complexity
For a detailed breakdown of how space cost compounds across nested structures, see space complexity of algorithms with examples.
For the lower triangular check specifically:
- Worst-case time: The inner loop runs (n-1) + (n-2) + … + 1 = n(n-1)/2 iterations. This is O(n²). The worst case occurs when every upper-triangle element is zero (the matrix is lower triangular) or the violation is at the very last upper-triangle position checked.
- Best-case time: mat[0][1] is non-zero. The function returns after one comparison. O(1).
- Space: O(1). The check reads the existing matrix in place. No auxiliary array, stack, or hash table is allocated. Only a fixed number of loop variables are created.
The n(n-1)/2 versus n² distinction matters when a placement question asks you to compare this with a brute-force full-matrix scan. The triangular scan checks roughly half the elements. Both are O(n²) in asymptotic terms because constants disappear, but the constant factor difference is real and worth noting if asked to optimise.
Relationship to Other Matrix Patterns
The lower triangular check is one of a family of index-condition checks on 2D arrays. The same two-loop skeleton handles all of them; only the condition changes.
Related patterns that appear in placement coding rounds:
- Upper triangular check: scan positions where the row index exceeds the column index (below the diagonal). If any such element is non-zero, the matrix is not upper triangular.
- Diagonal matrix check: combine both checks. Scan all off-diagonal positions; every one must be zero.
- Symmetric matrix check: for every (i, j) pair, verify that mat[i][j] equals mat[j][i]. The algorithm for finding symmetric pairs in an array applies the same index-swap intuition extended to a 2D grid.
- Scalar matrix check: verify the matrix is diagonal and all diagonal elements are equal.
Recognising this pattern family means you learn one skeleton and adapt it. If you can write the lower triangular check cleanly under time pressure, all four variants follow without a separate memorisation effort.
Where This Check Appears in Placement Tests
The GeeksforGeeks reference on the lower triangular check covers the standard implementation. Placement tests, however, go beyond that baseline.
Typical question variants in coding rounds:
- Detect and print whether the matrix is lower triangular.
- Print only the lower triangle (diagonal included) as a flat list.
- Count the non-zero elements in the lower triangle.
- Determine whether the matrix is both lower triangular and symmetric, which forces it to be a diagonal matrix.
- Given a matrix with some entries unknown, find the minimum number of changes needed to make it lower triangular.
The last two variants appear more frequently at product companies and analytics firms. They require extending the detection loop: instead of returning on the first violation, count or enumerate violations. That extension is a one-line change to the inner body.
The detection algorithm here, two nested loops that short-circuit on the first upper-triangle violation, is the same skeleton behind all five variants. TinkerLLM at ₹299 includes matrix problem sets that walk this pattern across types, with AI-graded output so you see immediately when your index logic is off.
Primary sources
Frequently asked questions
What makes a matrix lower triangular?
A square matrix is lower triangular when every element above the main diagonal is zero, that is mat[i][j] = 0 for all positions where the column index exceeds the row index. The diagonal elements and all elements below the diagonal can be any value, including zero.
Is the identity matrix a lower triangular matrix?
Yes. The identity matrix has 1s on the diagonal and 0s everywhere else, including all positions above the diagonal. That satisfies the definition of lower triangular, and also of upper triangular, making the identity matrix both simultaneously.
What is the time complexity of the lower triangular check?
O(n²) in the worst case. The two nested loops scan at most n(n-1)/2 positions above the diagonal. In the best case, when the very first upper-triangle element is non-zero, the check returns after a single comparison — effectively O(1).
What is the difference between lower and upper triangular matrices?
In a lower triangular matrix, all elements above the main diagonal are zero. In an upper triangular matrix, all elements below the main diagonal are zero. A diagonal matrix satisfies both definitions because all off-diagonal elements are zero.
Can a non-square matrix be lower triangular?
By the standard mathematical definition, triangular matrices are square. A non-square matrix can have a trapezoidal structure where one triangular region is all zeros, but the term lower triangular does not apply. Placement coding questions consistently assume square input.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)