Java ProgramsPatternsPrint Number Triangle

Print Number Triangle in Java

beginner·  Patterns  ·  Number Patterns

Problem

Each row of a number triangle restarts its own count from 1, so row i always ends at the number i — the row number and the row's last value are the same thing.

Given a number of rows, print a left-aligned triangle where row i contains the numbers 1 through i.

Input
n = 5
Output
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5

Java Program

Java
public class NumberTriangle { public static void main(String[] args) { int n = 5; for (int i = 1; i <= n; i++) { StringBuilder line = new StringBuilder(); for (int j = 1; j <= i; j++) { if (j > 1) line.append(" "); line.append(j); // resets to 1 at the start of every row } System.out.println(line); } } }

Output

1 1 2 1 2 3 1 2 3 4 1 2 3 4 5

Core Logic

Restarting a counter at 1 for every row, and running it up to that row's own number, prints each row's numbers independently of every other row.

How It Works
  1. 1The outer loop runs i from 1 to n, one iteration per row.
  2. 2The inner loop runs j from 1 to i, printing j at each step — so row i always ends with the value i itself.
  3. 3Because j is declared fresh inside the outer loop, it resets back to 1 at the start of every row.
  4. 4Each row is joined with a single space between the numbers and printed as one line.
For n = 5, row 3 prints 1 2 3 — three numbers, restarting from 1 — while row 5 prints 1 2 3 4 5.
💡

Key Point: The inner loop variable resetting to 1 every row is the whole idea here — the same loop shape as a star triangle, just printing the loop counter instead of a fixed character.

Complexity
Time Complexity: O(n²)Space Complexity: O(1)

Why: The total count of numbers printed across every row is 1+2+...+n, proportional to n², and only the loop counters are kept.

Key Concepts

nested for looprow-relative counting

Approach 2: Java 8

Java
import java.util.stream.Collectors; import java.util.stream.IntStream; public class NumberTriangleStream { public static void main(String[] args) { int n = 5; IntStream.rangeClosed(1, n) .mapToObj(i -> IntStream.rangeClosed(1, i) .mapToObj(String::valueOf) .collect(Collectors.joining(" "))) .forEach(System.out::println); } }

Output

1 1 2 1 2 3 1 2 3 4 1 2 3 4 5

Core Logic

Mapping each row's column positions directly to their own values, instead of a fixed row-wide value, reproduces the counting-up sequence one row at a time.

How It Works
  1. 1IntStream.rangeClosed(1, n) generates one stream element per row.
  2. 2For each row i, an inner IntStream.rangeClosed(1, i) generates that row's own values, 1 through i.
  3. 3.mapToObj(String::valueOf) converts each value to a String for joining.
  4. 4Collectors.joining(" ") joins that row's numbers before forEach prints it.
For row 4, the inner stream produces 1, 2, 3, 4 directly and joins them into "1 2 3 4".
💡

Key Point: The inner stream is re-created fresh for every row, the same as the inner loop's counter resetting each time — nothing carries over from one row's stream to the next.

Complexity
Time Complexity: O(n²)Space Complexity: O(1)

Why: The nested streams still produce one value per grid position across all rows, proportional to n², without collecting the full triangle.

Key Concepts

StreamIntStream.rangeClosed()Collectors.joining()

Related Programs