JavaScript Hollow Diamond Star Pattern

Beginner
8 min read
Updated: Sep 2026
3 programs
Live preview

What Is This Pattern?

A hollow diamond star pattern prints only the outline of a diamond: spaces fill the interior, and stars sit on the diagonals. Half-height rows means 2 * rows - 1 printed lines.

Remember
Rule: upper i = 1..rows, then lower i = rows-1..1
      On each row, append "*" where j === i or k === i

    *
   * *
  *   *
 *     *
*       *
 *     *
  *   *
   * *
    *       ← rows = 5 (9 lines)

Build it by stacking Program 7 (upper hollow V) and Program 8 (lower hollow V), starting the second outer loop at rows - 1 so the waist prints once.

How to Solve It

Print one hollow row with two inner loops, then call that idea twice — ascending, then descending past the waist.

MethodIdeaBest for
Dual outer loopsUpper 1..rows, lower rows-1..1, same j/k bodiesLearning, interviews, clearest stack of P7 + P8
Helper + ternaryOne printRow(i, rows) called from both halvesLess duplication once the geometry clicks

Pseudocode

Pseudocode
printHollowRow(i, rows):
    line = ""
    for j from rows down to 1:
        line += "*" if i === j else " "
    for k from 2 to rows:
        line += "*" if i === k else " "
    print line

for i from 1 to rows:          // upper half
    printHollowRow(i, rows)
for i from rows - 1 down to 1: // lower half (skip waist)
    printHollowRow(i, rows)

Cheat sheet

GoalPattern
Upper halffor (let i = 1; i <= rows; i++)
Lower half (no duplicate waist)for (let i = rows - 1; i >= 1; i--)
Left diagonalj from rows down to 1; star when i === j
Right diagonalk from 2 to rows; star when i === k
End the rowconsole.log(line); after both inner loops
Filled diamond nextProgram 10

Printing Stars vs Starting a New Line

APIEffectUse for
line += "*" / line += " "Stays on the same rowEach * or space
console.log(line)Ends the current rowAfter both j and k loops

Live Preview

Change the half-height and the hollow diamond updates instantly — including line and outline-star counts.

Whole numbers from 1 to 12. You get 2 * rows - 1 lines. Tap a chip or type a value — the preview redraws as you go.

Live result 5 half · 9 lines · 16 stars
    *    
   * *   
  *   *  
 *     * 
*       *
 *     * 
  *   *  
   * *   
    *    

Worked Walkthrough — rows = 4

Trace each outer value of i. Stars land where j === i (left leg) or k === i (right leg). Spaces show as ·.

HalfiPrinted rowStars
Upper1···*···1
Upper2··*·*··2
Upper3·*···*·2
Upper (waist)4*·····*2
Lower3·*···*·2
Lower2··*·*··2
Lower1···*···1

Lines: 4 + 3 = 7 = 2×4 - 1. Outline stars: 12 = 4×(4 - 1). Width of every line: 7.

JavaScript Programs

Three complete programs: fixed half-height, prompt input, and a reusable row helper. Use View Output for sample results, or Try It Yourself to edit and run in the playground.

Example 1 — Fixed rows = 5

Upper i = 1..rows, lower i = rows-1..1, same j/k bodies.

JavaScript
let rows = 5;

// Upper half: i = 1 .. rows
for (let i = 1; i <= rows; i++) {
  let line = "";
  for (let j = rows; j >= 1; j--) {
    if (i === j) {
      line += "*";
    } else {
      line += " ";
    }
  }
  for (let k = 2; k <= rows; k++) {
    if (i === k) {
      line += "*";
    } else {
      line += " ";
    }
  }
  console.log(line);
}

// Lower half: skip duplicate waist
for (let i = rows - 1; i >= 1; i--) {
  let line = "";
  for (let j = rows; j >= 1; j--) {
    if (i === j) {
      line += "*";
    } else {
      line += " ";
    }
  }
  for (let k = 2; k <= rows; k++) {
    if (i === k) {
      line += "*";
    } else {
      line += " ";
    }
  }
  console.log(line);
}
Try It Yourself

How It Works

1. Set half-height. rows = 5 means 5 upper lines and 4 lower lines (9 total).

2. Upper half grows outward. i runs from 1 to rows. Left loop j and right loop k append * only when they equal i.

3. Lower half mirrors without a second waist. i runs from rows - 1 down to 1 with the same inner logic.

4. Print the row. console.log(line) after both inner loops starts the next outline row.

Example 2 — User Input Version

Read the half-height at runtime with prompt. Prefer validating with Number.isFinite (shown in the tip below).

JavaScript
let rows = parseInt(prompt("Enter the number of rows:"), 10);

for (let i = 1; i <= rows; i++) {
  let line = "";
  for (let j = rows; j >= 1; j--) {
    line += (i === j) ? "*" : " ";
  }
  for (let k = 2; k <= rows; k++) {
    line += (i === k) ? "*" : " ";
  }
  console.log(line);
}

for (let i = rows - 1; i >= 1; i--) {
  let line = "";
  for (let j = rows; j >= 1; j--) {
    line += (i === j) ? "*" : " ";
  }
  for (let k = 2; k <= rows; k++) {
    line += (i === k) ? "*" : " ";
  }
  console.log(line);
}
Try It Yourself

How It Works

1. Prompt and parse. Ask for a half-height, then convert with parseInt(..., 10).

2. Same dual-half core. Only the source of rows changes — the print logic matches Example 1 (ternaries shorten the if/else).

3. Safer input tip. Bare parseInt yields NaN on letters or Cancel. Prefer:

Safer input
let rows = parseInt(prompt("Enter the number of rows:"), 10);
if (!Number.isFinite(rows) || rows < 1) {
  console.log("Enter a positive whole number.");
} else {
  // run the pattern loops here
}

Example 3 — Helper Function

Extract one row printer so the diamond reads as “upper, then lower.”

JavaScript
function printRow(i, rows) {
  let line = "";
  for (let j = rows; j >= 1; j--) {
    line += (i === j) ? "*" : " ";
  }
  for (let k = 2; k <= rows; k++) {
    line += (i === k) ? "*" : " ";
  }
  console.log(line);
}

let rows = 5;

for (let i = 1; i <= rows; i++) {
  printRow(i, rows);
}

for (let i = rows - 1; i >= 1; i--) {
  printRow(i, rows);
}
Try It Yourself

How It Works

1. One row recipe. printRow owns the j/k diagonal logic and the row break.

2. Call it twice. Upper half walks i up; lower half walks i down from rows - 1.

3. Same shape, less copy-paste. Learn the expanded loops first (Example 1), then refactor when the geometry feels familiar.

Edge Cases & Pitfalls

Check these before calling the solution done.

Lower starts at rows

Double waist

If the second outer loop starts at i = rows, the widest line prints twice. Use rows - 1.

k from 1

Extra center column

Right loop must start at k = 2. Starting at 1 overlaps the left half’s last column and skews the diamond.

console.log inside

Broken outline

If console.log sits inside j or k, the outline collapses into a column. Call it only after both inner loops.

Proportional font

Looks skewed in the IDE

Spaces and stars need a monospace font (console default is fine). Proportional fonts make diagonals look uneven.

rows = 1

Single star

Upper prints one line; lower never runs. Output is just * — a good sanity check.

Bad prompt

Guard against NaN

Cancel or letters yield NaN — check Number.isFinite(rows) before looping.

Time and Space Complexity

ProgramTimeExtra space
Dual loops (Examples 1–2)O(rows²)O(rows) for the line string
Helper function (Example 3)O(rows²)O(rows) for the line string

Lines printed = 2n - 1. Each line walks about 2n - 1 positions across the two inner loops, so work is still quadratic in n. Outline stars grow as 4(n - 1) for n ≥ 2 (and 1 when n = 1).

Key Takeaways

  • Compose halves: upper 1..rows then lower rows-1..1 — Programs 7 + 8 with one seam fix.
  • Diagonal rule: star only when i === j or i === k; everything else is a space.
  • Break the row: call console.log only after both inner loops.
  • Complexity: O(n²) time; O(n) for the row string.

One line: print hollow rows for i = 1..rows, then again for i = rows-1..1, starring only the diagonals.

Frequently Asked Questions

Two sequential outer loops share the same inner structure. The first runs i from 1 to rows (upper half). The second runs i from rows minus 1 down to 1 (lower half). On each row, j and k append stars when they equal i.
The first part already prints the widest row when i equals rows. Starting the second part at rows again would duplicate that waist line. rows minus 1 mirrors the upper half without a double middle.
Yes, by mapping a loop index to an effective row i or by branching on upper vs lower half. Splitting into two loops matches Programs 7 and 8 mentally and keeps each block easy to read.
rows + (rows - 1) = 2 * rows - 1 lines. Each line is also 2 * rows - 1 characters wide.
line += stays on the same row with no newline between characters. console.log(line) ends the row after both inner loops finish.
With n rows, about 2n - 1 printed lines, each with Theta(n) work across two inner loops, giving O(n²).
Program 9 draws only the outline (hollow). Program 10 fills every star in a solid diamond using spaces and 2*i-1 star runs.
Use parseInt(prompt(...), 10) and check Number.isFinite(rows) && rows >= 1 so bad input does not produce NaN rows.

Did you know?

This hollow diamond is a direct composition: Program 7’s upper half plus Program 8’s lower half with the duplicate middle row removed by starting the second phase at rows - 1. Total printed lines = 2 * rows - 1.

Next: Filled Diamond

Same half-stacking idea, but with solid centered star runs instead of a hollow outline.

Program 10 tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

12 people found this page helpful