Topics › Basics › Patterns

Pattern 6

Easy TUF ID 419 A2Z

Problem

Given an integer n, print an inverted numbered right pyramid: n rows, where the first row is 1 2 ... n, the second is 1 2 ... n-1, and so on down to a last row containing just 1. Numbers in a row are separated by single spaces.

Output format: every row ends with a newline, one space between numbers, no trailing space, and multi-digit numbers printed in full. n = 0 prints nothing.

Constraints: 0 ≤ n ≤ 100 is typical.

Example 1

n = 4

1 2 3 4
1 2 3
1 2
1

Row i (0-based) counts from 1 to n - i.

Example 2

n = 2

1 2
1

Two rows: the full count and then the single 1.

Shape and content, separately

Two earlier patterns combine here. The shape is the inverted triangle: row i (0-based) has n - i cells, so the inner bound decreases with the row. The content is the counting pyramid: the cell in column j (1-based) holds the value j. Once you separate the two questions, the loops write themselves: outer i from 0 to n - 1, inner j from 1 to n - i, body prints j.

As with every number pattern, keep values as int and let StringBuilder.append(int) or Integer.toString format them. Converting to char breaks at 10.

All approaches return the pattern as a String so the tests can compare it to expected literals.

Approach 1: Nested loops

Intuition. The inner counter is both the loop control and the value printed. Its upper bound n - i shrinks by one per row. The separator goes before every number except the first.

Algorithm.

  1. For i from 0 to n - 1:
  2. For j from 1 to n - i: if j > 1 append a space; append the number j.
  3. Append \n.
  4. Return the string.
static String nestedLoops(int n) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < n; i++) {
        for (int j = 1; j <= n - i; j++) {
            if (j > 1) sb.append(' ');
            sb.append(j);
        }
        sb.append('\n');
    }
    return sb.toString();
}

Complexity. Time O(n^2): n(n+1)/2 numbers are written. Space O(n^2) for the output, O(1) extra.

Verify the two boundary rows. For i = 0 the inner loop runs j = 1..n and writes the full count. For i = n - 1 the bound is n - (n - 1) = 1, so the loop runs once and writes "1". If your last row is empty, the bound was n - i - 1; if your first row has n + 1 entries, the bound was n - i + 1 with a 0-based i. Checking the first and last row is the fastest way to confirm a shrinking bound.

Approach 2: Build the upright rows, emit them in reverse

Intuition. The rows of this pattern are exactly the rows of the upright counting pyramid ("1", "1 2", "1 2 3", …) listed from longest to shortest. And those upright rows are easy to produce incrementally: each one is the previous one with " k" appended. So grow a row buffer, snapshot it into a list after every extension, and then walk the list backwards. No reversal utility is needed; a descending index does it.

Algorithm.

  1. Keep a row builder and a rows list.
  2. For k from 1 to n: if k > 1 append a space; append k; add row.toString() to rows.
  3. For i from rows.size() - 1 down to 0: append rows.get(i) and \n.
static String reversedRows(int n) {
    List<String> rows = new ArrayList<>();
    StringBuilder row = new StringBuilder();
    for (int i = 1; i <= n; i++) {
        if (i > 1) row.append(' ');
        row.append(i);
        rows.add(row.toString());
    }
    StringBuilder out = new StringBuilder();
    for (int i = rows.size() - 1; i >= 0; i--) out.append(rows.get(i)).append('\n');
    return out.toString();
}

Dry run for n = 3:

k row after extension rows
1 "1" ["1"]
2 "1 2" ["1", "1 2"]
3 "1 2 3" ["1", "1 2", "1 2 3"]

Walking backwards: "1 2 3\n1 2\n1\n".

Complexity. Time O(n^2); row.toString() copies O(k) characters at step k. Space O(n^2) for the list, which holds the whole pattern once, plus the output.

Approach 3: Stream over decreasing row lengths

Intuition. Describe the row lengths as the sequence n, n-1, ..., 1. IntStream.iterate(n, len -> len >= 1, len -> len - 1) generates exactly that: start at n, continue while the value is at least 1, step by -1. Each length maps to the row "1 2 ... len", built by an inner IntStream.rangeClosed(1, len) joined with spaces. The code states the pattern’s definition almost word for word.

Algorithm.

  1. IntStream.iterate(n, len -> len >= 1, len -> len - 1) for the lengths.
  2. For each len, join 1..len as strings with " ", then add \n.
  3. Collectors.joining() concatenates the rows.
static String streams(int n) {
    return IntStream.iterate(n, len -> len >= 1, len -> len - 1)
            .mapToObj(len -> IntStream.rangeClosed(1, len)
                    .mapToObj(j -> Integer.toString(j))
                    .collect(Collectors.joining(" ")) + "\n")
            .collect(Collectors.joining());
}

Complexity. Time O(n^2), space O(n) extra for one row at a time. For n = 0 the predicate 0 >= 1 fails immediately, the stream is empty, and the result is "".

The three-argument IntStream.iterate was added in Java 9; it is the stream equivalent of a classic for loop with a start value, a continuation test and a step.

Edge cases and pitfalls