Pattern Printing - Basic
Solve one Java logic problem at a time, then flip for the complete explanation and program.
Solve one Java logic problem at a time, then flip for the complete explanation and program.
Java Logic Development · Chapter 07 Companion Article
Fifteen star patterns — squares, triangles, pyramids, a diamond, hollow shapes, an X, and a plus — each derived from row-column conditions instead of memorized, so the same nested-loop thinking transfers to any new shape.
Pattern-printing problems are mainly used to test control over loops, conditions, row-column relationships, spacing, and boundary detection. The final pattern is visual, but the real skill is converting a shape into mathematical conditions.
Most basic pattern programs use:
System.out.print() to stay on the same line.System.out.println() to move to the next row.For a pattern containing n rows: i usually represents the current row, j usually represents the current column or item position. Solid patterns mainly depend on loop limits. Right-aligned patterns require leading spaces. Hollow patterns require boundary conditions. Symmetrical patterns often require an odd size. Pyramid patterns combine spaces and stars.
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= columns; j++) {
System.out.print("* ");
}
System.out.println();
}
The outer loop determines how many lines are printed. The inner loop determines what appears on each line.
A square contains the same number of rows and columns. For n = 5, every row contains five stars.
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
Run the outer loop n times. For every row, run the inner loop n times. Print one star during every inner-loop iteration. Both dimensions use the same value, which creates the square shape.
public class SquareStarPattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
For n = 5: row 1 prints 5 stars, row 2 prints 5 stars, the same process continues through row 5. Total stars printed = 5 × 5 = 25.
O(n²)O(1)Using different limits for rows and columns changes the square into a rectangle.
A square pattern is a simple way to demonstrate basic nested-loop understanding.
A rectangle uses different values for rows and columns. Example: rows = 4, columns = 6.
* * * * * *
* * * * * *
* * * * * *
* * * * * *
The outer loop controls height while the inner loop controls width. Unlike a square, the number of rows does not need to equal the number of columns.
public class RectangleStarPattern {
public static void main(String[] args) {
int rows = 4;
int columns = 6;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= columns; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
* * * * * *
* * * * * *
* * * * * *
* * * * * *
O(rows × columns)O(1)The important idea is separating vertical size from horizontal size.
A left triangle increases the number of stars by one on every row. For row i, print exactly i stars.
*
* *
* * *
* * * *
* * * * *
For each row, stars = current row number. Therefore: row 1 → 1 star, row 2 → 2 stars, row 3 → 3 stars, row 5 → 5 stars.
public class LeftTrianglePattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
*
* *
* * *
* * * *
* * * * *
For row i = 4, the condition is j <= 4. Therefore four stars are printed.
The total number of iterations is 1 + 2 + 3 + ... + n. Therefore:
O(n²)O(1)Using j <= n prints the same number of stars on every row instead of forming a triangle.
A right triangle is right-aligned. Each row contains leading spaces followed by stars.
*
* *
* * *
* * * *
* * * * *
For row i: spaces = n - i, stars = i.
| Row | Spaces | Stars |
|---|---|---|
| 1 | 4 | 1 |
| 2 | 3 | 2 |
| 3 | 2 | 3 |
| 4 | 1 | 4 |
| 5 | 0 | 5 |
Because "* " occupies two character positions, " " is used for indentation.
public class RightTrianglePattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int space = 1; space <= n - i; space++) {
System.out.print(" ");
}
for (int star = 1; star <= i; star++) {
System.out.print("* ");
}
System.out.println();
}
}
}
*
* *
* * *
* * * *
* * * * *
O(n²)O(1)Right-aligned patterns test whether you can calculate both indentation and visible elements from the row number.
The inverted left triangle starts with n stars and removes one star from every following row.
* * * * *
* * * *
* * *
* *
*
For row i: stars = n - i + 1. For n = 5: row 1 → 5, row 2 → 4, row 3 → 3, row 4 → 2, row 5 → 1.
public class InvertedLeftTriangle {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
* * * * *
* * * *
* * *
* *
*
The inner loop can also be written as:
for (int j = 1; j <= n - i + 1; j++) {
System.out.print("* ");
}
O(n²)O(1)This pattern decreases the stars while increasing leading spaces.
* * * * *
* * * *
* * *
* *
*
For row i: spaces = i - 1, stars = n - i + 1. One quantity increases while the other decreases.
public class InvertedRightTriangle {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int space = 1; space < i; space++) {
System.out.print(" ");
}
for (int star = i; star <= n; star++) {
System.out.print("* ");
}
System.out.println();
}
}
}
* * * * *
* * * *
* * *
* *
*
O(n²)O(1)Increasing spaces without decreasing stars produces an incorrectly shifted rectangle rather than an inverted triangle.
A pyramid combines decreasing leading spaces with an increasing odd number of stars.
*
***
*****
*******
*********
For row i: spaces = n - i, stars = 2 × i - 1. The star sequence becomes 1, 3, 5, 7, 9.
public class PyramidPattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int space = 1; space <= n - i; space++) {
System.out.print(" ");
}
for (int star = 1; star <= 2 * i - 1; star++) {
System.out.print("*");
}
System.out.println();
}
}
}
*
***
*****
*******
*********
For row 4: spaces = 5 - 4 = 1, stars = 2 × 4 - 1 = 7. Result: *******
Each new row expands by one position on the left and one on the right. That adds two stars: 1 → 3 → 5 → 7 → 9.
O(n²)O(1)Remember the relationship 2 * i - 1. It appears frequently in pyramid and diamond problems.
An inverted pyramid begins at maximum width and gradually becomes narrower.
*********
*******
*****
***
*
For row i: leading spaces = i - 1, stars = 2 × (n - i) + 1. For n = 5, stars are 9, 7, 5, 3, 1.
public class InvertedPyramidPattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int space = 1; space < i; space++) {
System.out.print(" ");
}
for (int star = 1; star <= 2 * (n - i) + 1; star++) {
System.out.print("*");
}
System.out.println();
}
}
}
*********
*******
*****
***
*
O(n²)O(1)This is the reverse relationship of a normal pyramid: spaces increase, stars decrease by two.
A diamond can be treated as two connected parts: a normal pyramid, then an inverted pyramid without repeating the middle row.
*
***
*****
*******
*********
*******
*****
***
*
For the upper half: spaces decrease, stars increase. For the lower half: spaces increase, stars decrease. The lower loop begins at n - 1 so the widest row is not printed twice.
public class DiamondPattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int space = 1; space <= n - i; space++) {
System.out.print(" ");
}
for (int star = 1; star <= 2 * i - 1; star++) {
System.out.print("*");
}
System.out.println();
}
for (int i = n - 1; i >= 1; i--) {
for (int space = 1; space <= n - i; space++) {
System.out.print(" ");
}
for (int star = 1; star <= 2 * i - 1; star++) {
System.out.print("*");
}
System.out.println();
}
}
}
*
***
*****
*******
*********
*******
*****
***
*
A diamond created with height parameter n contains 2n - 1 rows. For n = 5: 2 × 5 - 1 = 9 rows.
O(n²)O(1)Starting the second half from n prints the middle row twice.
A hollow square prints stars only on its outer boundary.
* * * * *
* *
* *
* *
* * * * *
Print a star when the current position belongs to: first row (i == 1), last row (i == n), first column (j == 1), or last column (j == n). Combined condition: i == 1 || i == n || j == 1 || j == n. Otherwise print spaces.
public class HollowSquarePattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == 1 || i == n || j == 1 || j == n) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
* * * * *
* *
* *
* *
* * * * *
Every cell on a square's border belongs to at least one of its four edges. Interior cells satisfy none of those conditions.
O(n²)O(1)Hollow patterns are mainly boundary-condition problems rather than star-counting problems.
A hollow rectangle uses the same boundary idea as a hollow square, but row and column counts differ.
* * * * * *
* *
* *
* * * * * *
Print a star when i == 1 || i == rows || j == 1 || j == columns. Otherwise print spaces.
public class HollowRectanglePattern {
public static void main(String[] args) {
int rows = 4;
int columns = 6;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= columns; j++) {
if (i == 1 || i == rows || j == 1 || j == columns) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
* * * * * *
* *
* *
* * * * * *
O(rows × columns)O(1)If either dimension is very small, such as one or two rows, little or no interior space exists. The boundary logic still works.
A hollow left triangle prints the left edge, the diagonal edge, and the complete bottom edge.
*
* *
* *
* *
* * * * *
For row i and column j, print a star when j == 1 (left edge), j == i (diagonal edge), or i == n (bottom edge).
public class HollowTrianglePattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
if (j == 1 || j == i || i == n) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
*
* *
* *
* *
* * * * *
At row 4: j = 1 → star, j = 2 → space, j = 3 → space, j = 4 → star. Only both triangle edges remain visible.
O(n²)O(1)Checking only j == 1 || j == i leaves the bottom row hollow instead of closing the triangle.
A hollow pyramid prints only its two sloping boundaries and its bottom base.
*
* *
* *
* *
*********
Consider each row width as 2 * i - 1. Within that row, print stars only when j == 1 (left sloping boundary), j == 2 * i - 1 (right sloping boundary), or i == n (bottom edge). Leading spaces position the row correctly.
public class HollowPyramidPattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int space = 1; space <= n - i; space++) {
System.out.print(" ");
}
for (int j = 1; j <= 2 * i - 1; j++) {
if (j == 1 || j == 2 * i - 1 || i == n) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
*
* *
* *
* *
*********
The width of each pyramid row increases by two. The first and last positions of that width form the two diagonal edges.
O(n²)O(1)Do not try to memorize the entire program. Identify three independent components: leading spaces, current row width, and boundary positions.
An X pattern is created using the two diagonals of a square matrix. For an n × n grid: main diagonal i == j, opposite diagonal i + j == n + 1.
* *
* *
*
* *
* *
Some star coordinates are: (1,1) and (1,5); (2,2) and (2,4); (3,3); (4,2) and (4,4); (5,1) and (5,5).
public class XPattern {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j || i + j == n + 1) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
* *
* *
*
* *
* *
For the opposite diagonal when n = 5: (1,5) → 1 + 5 = 6, (2,4) → 2 + 4 = 6, (3,3) → 3 + 3 = 6, (4,2) → 4 + 2 = 6, (5,1) → 5 + 1 = 6. Every coordinate has the same sum: n + 1.
O(n²)O(1)The X pattern introduces matrix-coordinate thinking, which is useful beyond pattern questions.
A plus pattern places stars along the middle row and middle column. It is easiest to construct using an odd value of n. For n = 5, middle = n / 2. With zero-based indexing, middle = 2.
*
*
* * * * *
*
*
Print a star when i == middle || j == middle. This means the position belongs to either the middle row or the middle column.
public class PlusPattern {
public static void main(String[] args) {
int n = 5;
int middle = n / 2;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == middle || j == middle) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
*
*
* * * * *
*
*
An odd-sized grid has exactly one center row and one center column. For n = 5, index 2 is the unique center. With an even value such as n = 6, there is no single central row and column, so the definition of the plus shape must be adjusted.
O(n²)O(1)Solid and hollow patterns require different reasoning.
Every valid position receives a star. Example:
* * *
* * *
* * *
The main concern is deciding how many times the inner loop should run.
Only boundary positions receive stars. Example:
* * *
* *
* * *
The main concern is determining whether the current (row, column) position belongs to an edge. This usually requires if conditions inside nested loops.
| Pattern | Spaces | Stars / Condition |
|---|---|---|
| Square | 0 | n |
| Rectangle | 0 | columns |
| Left Triangle | 0 | i |
| Right Triangle | n - i | i |
| Inverted Left Triangle | 0 | n - i + 1 |
| Inverted Right Triangle | i - 1 | n - i + 1 |
| Pyramid | n - i | 2 * i - 1 |
| Inverted Pyramid | i - 1 | 2 * (n - i) + 1 |
| Diamond | Depends on half | Odd-number sequence |
| Hollow Square | 0 | Four boundaries |
| Hollow Rectangle | 0 | Four boundaries |
| Hollow Triangle | 0 | Left, diagonal, bottom |
| Hollow Pyramid | n - i | Two edges and base |
| X | 0 | Two diagonals |
| Plus | 0 | Middle row or column |
Pattern problems become easier when the output is treated as a coordinate grid. For example, consider:
* *
* *
*
* *
* *
Instead of asking "How do I print an X?", ask "At which (i, j) positions should a star appear?" The answer becomes i == j || i + j == n + 1. This approach is especially effective for hollow shapes, diagonal patterns, X patterns, plus patterns, boxes, borders, and matrix-style patterns.
Use the following process during practice or interviews.
Determine how many output lines are required.
For each row, identify leading spaces, stars, internal spaces, and trailing content if any.
Ask whether each quantity increases, decreases, remains constant, or changes only at boundaries.
Examples: stars = i, stars = n - i + 1, spaces = n - i, stars = 2 * i - 1.
For hollow or geometric patterns, determine whether the current cell is first row, last row, first column, last column, main diagonal, opposite diagonal, middle row, or middle column.
Values such as n = 3 or n = 5 make incorrect formulas easy to detect.
Pattern formatting depends heavily on these methods.
Prints content without automatically moving to the next line. Example: System.out.print("* ");. Calling it repeatedly produces * * * * *.
Moves the cursor to the next output line. It is normally called after the inner loop:
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
System.out.print("* ");
}
System.out.println();
}
Placing println() inside the inner loop would incorrectly place each star on a separate line.
Spaces are part of the pattern logic, not merely decoration. Consider:
*
* *
* * *
No indentation is required. But:
*
* *
* * *
requires spaces before each row. If stars are printed using System.out.print("* "); then indentation may also need two spaces: System.out.print(" ");. If stars are printed without trailing spaces using System.out.print("*"); then one-space indentation is generally sufficient: System.out.print(" ");. Consistent character width prevents distorted output.
Both approaches are valid.
for (int i = 1; i <= n; i++) {
}
This style often makes formulas easier to understand: 2 * i - 1.
for (int i = 0; i < n; i++) {
}
This style is convenient when working with arrays, matrix indexes, middle positions, and coordinate conditions. For example, int middle = n / 2; is natural with zero-based indexing.
The important rule is consistency. Mixing one-based and zero-based formulas is a common source of off-by-one errors.
For small interview examples, repeated System.out.print() calls are easy to understand. When building a pattern as a string, StringBuilder is more suitable. Example:
public class PatternWithStringBuilder {
public static void main(String[] args) {
int n = 5;
StringBuilder pattern = new StringBuilder();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
pattern.append("* ");
}
pattern.append(System.lineSeparator());
}
System.out.print(pattern);
}
}
*
* *
* * *
* * * *
* * * * *
This approach separates pattern construction from output operations.
Hard-coded values are convenient for demonstrations. Real programs can accept the size from the user.
import java.util.Scanner;
public class UserInputPattern {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter number of rows: ");
int n = scanner.nextInt();
if (n <= 0) {
System.out.println("Number of rows must be positive.");
return;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
For input 4, the pattern portion of the output is:
*
* *
* * *
* * * *
Input validation prevents meaningless negative or zero-sized patterns when positive dimensions are required.
Most basic pattern programs are described as O(n²) because they process approximately n × n output positions. Examples: square n² stars, X checks n² positions, hollow square checks n² positions, plus checks n² positions.
Triangles do not execute exactly n² inner iterations. For example, 1 + 2 + ... + n = n(n + 1) / 2. However, asymptotically this is still O(n²).
When the pattern is printed directly: O(1) auxiliary space. The loop variables consume constant extra memory regardless of n. When the complete output is stored in a StringBuilder, space complexity grows with the generated pattern size.
Pattern-printing programs physically generate characters. A program cannot generally print an n × n filled pattern in less than O(n²) output work because approximately n² characters or symbols must be produced. Therefore, optimization in pattern problems usually focuses more on correct formulas, clean conditions, avoiding unnecessary loops, and readable implementation rather than trying to reduce every pattern to linear time.
Incorrect:
for (int j = 1; j <= n; j++) {
System.out.println("* ");
}
Each star moves to a new line. Correct:
for (int j = 1; j <= n; j++) {
System.out.print("* ");
}
System.out.println();
Using < instead of <= can remove one row or one star. Example: for (int i = 1; i < n; i++) { } executes only n - 1 times.
For a right triangle or pyramid, incorrect indentation changes the entire shape. Always derive the space count from the current row instead of adjusting it by trial and error.
Using System.out.print("* "); with System.out.print(" "); can make right-aligned patterns appear shifted because the visible star unit has two characters while the space unit has one.
When joining two pyramids, the lower half should normally begin from n - 1.
Using logical AND instead of OR is a frequent mistake. Incorrect: i == 1 && i == n — a row cannot normally be both the first and last row. Correct boundary logic uses OR: i == 1 || i == n || j == 1 || j == n.
Hollow triangle and hollow pyramid programs must explicitly print the final row completely.
Printing three separate System.out.println() calls with literal star strings may reproduce one fixed pattern, but it does not demonstrate pattern-generation logic. The solution should work for variable n.
Instead of memorizing dozens of programs, recognize these relationships.
Think: stars = i
Think: stars = n - i + 1
Think: spaces + stars = n
Think: stars = odd numbers, therefore stars = 2 * i - 1
Think: "Which coordinates belong to the boundary?"
Think: "Which row-column relationship identifies the diagonal?"
These expressions are useful across many pattern problems.
| Purpose | Condition |
|---|---|
| First row | i == 1 |
| Last row | i == n |
| First column | j == 1 |
| Last column | j == n |
| Main diagonal | i == j |
| Opposite diagonal | i + j == n + 1 |
| Zero-based opposite diagonal | i + j == n - 1 |
| Middle row | i == n / 2 |
| Middle column | j == n / 2 |
| Triangle diagonal | i == j |
| Pyramid stars | 2 * i - 1 |
| Increasing spaces | i - 1 |
| Decreasing spaces | n - i |
These should be understood as coordinate relationships rather than memorized blindly.
| Pattern | Main Skill Tested |
|---|---|
| Square | Basic nested loops |
| Rectangle | Independent dimensions |
| Left Triangle | Row-dependent loop limit |
| Right Triangle | Leading-space calculation |
| Inverted Left Triangle | Decreasing iteration count |
| Inverted Right Triangle | Increasing spaces and decreasing stars |
| Pyramid | Odd-number relationship |
| Inverted Pyramid | Reverse pyramid relationship |
| Diamond | Combining symmetric halves |
| Hollow Square | Boundary detection |
| Hollow Rectangle | Boundary detection with separate dimensions |
| Hollow Triangle | Multiple edge conditions |
| Hollow Pyramid | Width and boundary coordination |
| X | Diagonal coordinate conditions |
| Plus | Center row and center column |
When an interviewer gives a new pattern, avoid immediately writing loops. First describe the pattern mathematically. For every row, determine:
For example, for:
*
***
*****
You can immediately derive spaces = n - i and stars = 2 * i - 1. Once those relationships are correct, converting them to Java loops becomes straightforward.
After understanding the basic versions, useful variations include:
These variations improve logic development without requiring completely different programming concepts.
A basic pattern can be separated into a reusable method.
public class ReusablePattern {
public static void printLeftTriangle(int n) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
public static void main(String[] args) {
printLeftTriangle(5);
}
}
*
* *
* * *
* * * *
* * * * *
Using methods keeps pattern logic separate from program setup and makes testing different sizes easier.
Before considering a pattern solution complete, verify:
2 * i - 1.O(n²) time.O(1) auxiliary space.