Pattern 1
Java source ↗ Edit this article ↗
Jump to code:
Problem
Given an integer n, print a solid square of stars: n rows, each containing n stars separated by single spaces. This is the first of the classic pattern-printing exercises. Its job is not to be hard; it is to make the two-loop skeleton that every later pattern reuses feel automatic, so that when the shapes get trickier you only have to think about what goes in each cell, never about the loops themselves.
Output format used in this article and in the Java file: every row ends with a newline (including the last one), stars in the same row are separated by exactly one space, and there is no trailing space after the last star. Most judges ignore trailing whitespace, but a precise format is what makes the solutions testable with string equality.
Constraints: 0 ≤ n ≤ 100 is typical. n = 0 prints nothing at all.
Example 1
n = 4
* * * *
* * * *
* * * *
* * * *
Four rows and four columns: n controls both dimensions.
Example 2
n = 1
*
A single cell, so there is no separator anywhere.
How to read any pattern
Before any code, settle four things. First, count the rows: that is the outer loop. Second, for one row, count the columns: that is the inner loop, and its bound may depend on the row index. Third, decide what belongs in cell (i, j): a star, a space, a digit, a letter. Fourth, end every row with a newline. For this pattern the answers are n, n, “always a star” and “yes”, so the inner bound does not depend on the outer index yet. That independence is exactly what makes it the warm-up.
All approaches below return the pattern as a String instead of printing character by character. Returning a string keeps the code testable (main compares it to an expected literal) and the caller prints it with a single System.out.print.
Approach 1: Nested loops
Intuition. Rows are the outer loop and columns are the inner loop. Inside the inner loop we emit one cell. The only subtlety is the separator: a space belongs between two stars, not after every star, so we emit a space before each star except the first in its row. That “fencepost” check is the standard way to avoid trailing spaces.
Algorithm.
- Create a
StringBuilder. - For
ifrom0ton - 1(rows): - For
jfrom0ton - 1(columns): ifj > 0append a space, then append*. - After the inner loop append
\n. - Return the built string.
static String nestedLoops(int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j > 0) sb.append(' ');
sb.append('*');
}
sb.append('\n');
}
return sb.toString();
}
Complexity. Time O(n^2): there are n^2 cells and each costs constant time. Space O(n^2) for the output itself, which is unavoidable since the answer has that many characters; the extra working memory is O(1).
Approach 2: One loop over the flat index
Intuition. The grid has n * n cells. Number them 0, 1, ..., n*n - 1 row by row. Cell k sits in row k / n and column k % n. With that mapping a single loop can walk the whole grid and still know when a row ends: whenever the column k % n equals n - 1. The output is identical; what changes is where the two-dimensional structure lives, in the arithmetic rather than in a second loop.
This is worth knowing in its own right. The same k / n, k % n mapping is how a 2-D matrix is stored in a 1-D array, and it reappears in problems such as binary search over a sorted matrix, where you treat the matrix as one long sorted list.
Algorithm.
- For
kfrom0ton*n - 1: computej = k % n. - If
j > 0append a space; append*. - If
j == n - 1, the row is complete, so append\n.
static String singleLoop(int n) {
StringBuilder sb = new StringBuilder();
for (int k = 0; k < n * n; k++) {
int j = k % n; // column of cell k (the row would be k / n)
if (j > 0) sb.append(' ');
sb.append('*');
if (j == n - 1) sb.append('\n'); // last column: close the row
}
return sb.toString();
}
Complexity. Time O(n^2), one iteration per cell, with a division and a modulo each, which are constant time. Space O(1) beyond the output.
Note that for n = 0 the loop condition k < 0 is false immediately, so k % n is never evaluated and there is no division by zero.
Approach 3: Build one row, repeat it
Intuition. Every row of this pattern is the same string, "* * ... *". So build that row once and repeat it n times. Collections.nCopies(n, "*") is a list of n stars, String.join(" ", list) glues them with single spaces and no trailing space, and String.repeat(n) stacks n copies of row + "\n". There is no explicit loop at all; the Java library does the iteration.
Algorithm.
row = String.join(" ", Collections.nCopies(n, "*")).- Return
(row + "\n").repeat(n).
static String repeatRow(int n) {
String row = String.join(" ", Collections.nCopies(n, "*"));
return (row + "\n").repeat(n);
}
Dry run for n = 3:
| step | value |
|---|---|
nCopies(3, "*") |
["*", "*", "*"] |
join(" ", ...) |
"* * *" |
row + "\n" |
"* * *\n" |
.repeat(3) |
"* * *\n* * *\n* * *\n" |
Complexity. Time O(n^2), dominated by copying the row n times. Space O(n) extra for the single row, plus the output.
For n = 0 this still works without a special case: nCopies(0, "*") is an empty list, join returns "", and "\n".repeat(0) is "", so the result is the empty string, matching the loop versions.
Edge cases and pitfalls
n = 0. All three methods return"". Make sure your loops use<againstnrather than<=, or you will print one row too many.n = 1. One star and no separator. Thej > 0check is what makes this come out as"*"instead of" *"or"* ".- Trailing space. Writing
sb.append("* ")inside the inner loop is shorter but leaves a space at the end of each row. Put the separator before every star except the first, or strip it afterwards. printversusprintln. The returned string already ends with\n, so print it withSystem.out.print. Usingprintlnadds an extra blank line at the end.- Line endings.
'\n'is what judges expect.System.lineSeparator()is"\r\n"on Windows and would break string comparison. - String concatenation in a loop.
s += "*"creates a new string every time and is quadratic per row in the worst case.StringBuilderis the right tool whenever you build output piece by piece. - Mixing up the counters. Using
iin both loops, or writingj < iby habit, prints a triangle instead of a square. In this pattern both bounds aren. - Overflow in
n * n. Harmless at pattern sizes, butn * noverflowsintoncenexceeds 46340. Keep it in mind when you reuse the flat-index trick on real matrices.