Java ProgramsPatternsPrint Multiplication Triangle

Print Multiplication Triangle in Java

intermediate·  Patterns  ·  Number Patterns

Problem

Each row of this triangle is a short slice of one number's multiplication table — row i shows i multiplied by 1 through i, using the row index as both the row's identity and its multiplier.

Given a number of rows, print a triangle where row i contains i multiplied by every value from 1 to i.

Input
5
Output
1 2 4 3 6 9 4 8 12 16 5 10 15 20 25

Java Program

Java
public class MultiplicationTriangle { public static void main(String[] args) { int n = 5; for (int i = 1; i <= n; i++) { StringBuilder row = new StringBuilder(); for (int j = 1; j <= i; j++) { if (j > 1) row.append(" "); row.append(i * j); // row i's own multiplication table, term j } System.out.println(row); } } }

Output

1 2 4 3 6 9 4 8 12 16 5 10 15 20 25

Core Logic

Multiplying the row number by each position from 1 up to the row number itself fills every row with that row's own multiplication table, growing one term longer each time.

How It Works
  1. 1The outer loop runs i from 1 to n, one row per row number.
  2. 2The inner loop runs j from 1 to i, one term per column in that row.
  3. 3Each position prints i * j — row i's own multiplication table, truncated to i terms.
  4. 4Row i ends up i terms wide, the same growth pattern as Number Triangle.
Row 3 computes 3*1, 3*2, 3*3, giving 3 6 9.
💡

Key Point: Every row uses a different multiplier — row 3's values (3, 6, 9) and row 4's values (4, 8, 12, 16) come from entirely separate multiplication tables, unlike Print Multiplication Table, which always tables the same fixed number.

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

Why: The total multiplications performed across every row grows proportionally to n², with no storage beyond the loop counters and a per-row StringBuilder.

Key Concepts

nested for loopmultiplication

Approach 2: Java 8

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

Output

1 2 4 3 6 9 4 8 12 16 5 10 15 20 25

Core Logic

Mapping each column position to that row's own multiple, instead of to the position itself, produces each row's slice of its multiplication table directly.

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 column positions 1 through i.
  3. 3.mapToObj(j -> String.valueOf(i * j)) multiplies the row number by each position.
  4. 4Collectors.joining(" ") joins that row's products before forEach prints it.
For row 3, the inner stream maps 1, 2, 3 to 3*1, 3*2, 3*3, giving "3 6 9".
💡

Key Point: The row index i is captured by the inner lambda from the outer stream — each row's multiplication table depends on knowing which row it's currently building.

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

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

Key Concepts

StreamIntStream.rangeClosed()Collectors.joining()

Related Programs