Phase 02 — Projects

Phase 02 has one goal: turn abstract pattern knowledge into muscle memory and public evidence. Three deliverables do that. The first is your training log (the 150-problem repo), the second is the deep-work project that proves you understand the internals (MiniCollections), and the third is the public teaching artifact (the blog post) that hiring managers actually find on Google when they search your name. Do them in this order — the blog post gets written after you have solved enough problems to have something worth teaching.


Project A — java-dsa-150 (the 150-problem tracker)

Time: 60-80 hours, spread across weeks 4-9 of the phase (this is the phase, essentially).

Goal: solve 150 LeetCode problems (60 Easy / 70 Medium / 20 Hard), one file per problem, every solution pattern-tagged, all in one public GitHub repo. Recruiters check this. So do hiring managers before onsites.

Repo structure

java-dsa-150/
├── README.md                    # progress table, patterns index, retros
├── pom.xml                      # Maven, junit-jupiter 5.10+, java.version 21
├── src/
│   ├── main/java/dsa/
│   │   ├── arrays/
│   │   │   ├── LC0001_TwoSum.java
│   │   │   ├── LC0011_ContainerWithMostWater.java
│   │   │   └── …
│   │   ├── strings/
│   │   ├── linkedlist/
│   │   ├── trees/
│   │   ├── graphs/
│   │   ├── dp/
│   │   ├── heap/
│   │   ├── stack/
│   │   └── misc/
│   └── test/java/dsa/           # mirror of main
└── docs/
    ├── patterns.md              # every pattern seen, linked to problems
    └── retros/                  # weekly what-worked/what-didn't

Per-problem file template

Every solved file starts with a header comment. This is what makes the repo a learning tool instead of a dumping ground.

package dsa.arrays;

/**
 * LeetCode 1 — Two Sum   (Easy)
 * https://leetcode.com/problems/two-sum/
 *
 * Pattern:    hash map for O(1) lookup
 * Tried:      brute force nested loop O(n²) → hash map in one pass O(n)
 * Time:       O(n)
 * Space:      O(n)
 * Solved in:  8 min (target: 10)
 * Retry?:     No
 */
public final class LC0001_TwoSum {
    public int[] twoSum(int[] nums, int target) {  }
}

Required practices

  • One test per solution. Not a full suite — just enough to prove it runs on the given example plus one edge case.

  • Every commit references the problem number: LC0300: LIS O(n log n) with patience sort.

  • docs/patterns.md is a table: pattern → list of LC#### links. Sort by pattern and by problem number both. This is what you review before an study.

  • Weekly retro in docs/retros/YYYY-WW.md: what you solved, what you got stuck on, what pattern you should drill next week.

Progress table in the README

Keep it visible — progress-porn is motivating and recruiters skim it.

| Category | Easy | Medium | Hard | Total |
|---|---|---|---|---|
| Arrays & Strings | 12 | 18 | 3 | 33 |
| Linked Lists      |  4 |  6 | 1 | 11 |
| Trees             |  8 | 12 | 3 | 23 |
| Graphs            |  4 |  8 | 3 | 15 |
| DP                |  6 | 12 | 5 | 23 |
| Heap/Priority     |  4 |  6 | 2 | 12 |
| Stack/Deque       |  6 |  4 | 1 | 11 |
| Misc / Design     | 16 |  4 | 2 | 22 |
| **Total**         | **60** | **70** | **20** | **150** |

Acceptance criteria

  • 150 files, all compiling, all with main-suite tests passing (mvn test clean).

  • Every file has the header comment with pattern, complexity, and solve time.

  • docs/patterns.md covers every pattern from 06_problem_solving_strategy.md.

  • Repo has ≥ 4 weekly retros.

  • README has a live progress table and a “how to browse” section for recruiters.

⚠️ What most people get wrong: they push “I solved it” without the header comment. Six months later they can’t remember why they used a hash map, and the repo becomes useless. The header is the whole point.


Project B — mini-collections (from-scratch collections library)

Time: 20-25 hours over 2 weeks.

Goal: re-implement ArrayList, LinkedList, HashMap, and PriorityQueue from scratch, with a JUnit 5 test suite, hitting ≥ 90 % branch coverage measured by JaCoCo. This is the project that proves you understand the machinery under the collections, not just the API.

What to build

Class

API to match

Non-negotiable requirements

MiniArrayList<E>

add, get, set, remove(int), size, iterator, clear

Backing Object[], grow 1.5× on capacity hit, ConcurrentModificationException on structural change during iteration

MiniLinkedList<E>

Same + addFirst, addLast, removeFirst, removeLast

Doubly-linked, head/tail sentinels are fine, iterator is fresh each call

MiniHashMap<K,V>

put, get, remove, containsKey, size, entrySet

Chaining via Node[], resize at load factor 0.75, initial capacity 16, hash spread (h = key.hashCode()) ^ (h >>> 16)

MiniPriorityQueue<E>

offer, poll, peek, size, iterator

Array-backed binary heap, Comparator<? super E> in constructor, sift-up / sift-down

Do not touch red-black trees or fancy resizing schemes for MiniHashMap — chained hashing is enough to teach the lesson. The point is you can explain every line, not that you match java.util.HashMap byte-for-byte.

Testing discipline

Use JUnit 5 with parameterised tests. Aim for these categories per class:

  • Happy path — add N, get N, size == N.

  • Growth — add enough elements to force resize; internal capacity should double / grow correctly.

  • Removal — remove from head, middle, tail. After removals, size and iteration order both correct.

  • Iterationfor-each walks in insertion order (for list); throws ConcurrentModificationException on structural modification.

  • Nulls — for MiniHashMap, null key allowed only in bucket 0; null value allowed everywhere; document your choice.

  • Comparator — for MiniPriorityQueue, test with both natural order and a Comparator.reverseOrder().

Run mvn verify and JaCoCo (org.jacoco:jacoco-maven-plugin). If a branch is uncovered, the code is either dead or a bug waiting to happen — delete or test it.

Acceptance criteria

  • All four classes compile against Java 21 with no warnings.

  • mvn verify clean, JaCoCo branch coverage ≥ 90 %.

  • Each class has a package-private benchmark test comparing throughput against the java.util.* equivalent (informational; you will lose, that’s fine — goal is understanding why).

  • README explains for each class: the invariant, the growth policy, and one thing you deliberately did worse than the JDK.

⚠️ What most people get wrong: they “finish” the project without writing the invariant down. Then a reviewer asks “what’s the invariant of your heap after poll?” and they freeze. Write the invariants in the class Javadoc before you write the methods.


Project C — Blog post: “20 DSA patterns that solve 80 % of LeetCode”

Time: 6-10 hours, split across weeks 8-9.

Goal: publish a technical blog post on Medium, dev.to, or your own site. Length ~1500-2500 words. Purpose: forces you to teach the patterns, which is the fastest way to find your own blind spots. Bonus: it shows up when a recruiter Googles your name.

Outline (use this exactly, edit later)

  1. Intro (150 words) — why patterns beat memorization. Concrete stat: “of 150 problems I solved, 20 patterns covered 128 of them.”

  2. The pattern signature table (400 words) — the same table from 06_problem_solving_strategy.md, in your own words with 2-3 example problems per row.

  3. Deep dive: 3 patterns you now know cold (900 words) — pick your three strongest: sliding window, two pointers, DP-on-sequences. Each with one worked example in Java, complexity, and a “why this pattern works” paragraph.

  4. The five-step process (300 words) — clarify → examples → brute → optimize → code. Give one study-style walk-through.

  5. Anti-patterns / lessons learned (250 words) — the 3 mistakes you made most often and how you stopped making them.

  6. CTA + repo link (100 words) — link to java-dsa-150, invite feedback.

Publishing checklist

  • Code blocks are Java 21, not Java 8. Use var, List.of, records where they fit.

  • Every code block has been copy-pasted into a .java file and compiled — no untested snippets.

  • Featured image is your own diagram, not a stock photo of “hacker in hoodie.”

  • Cross-post: publish on one platform first (dev.to or your own blog), get it working, then syndicate to Medium and LinkedIn.

  • Include a short bio + link to your GitHub. Recruiters will click both.

Acceptance criteria

  • Post is live at a public URL.

  • ≥ 3 people read it and give feedback (peer, mentor, or a Discord community). Even one “this was helpful” reply counts.

  • URL added to your GitHub profile README and LinkedIn.

  • One follow-up post drafted in docs/blog/next-post.md for later phases.

⚠️ What most people get wrong: they wait until they “know enough” to write. You do not need to be an expert to explain 20 patterns — you need to have practiced them. The act of writing surfaces the gaps. Write it now, iterate later.


Cross-project skill coverage

Here is what each project actually trains, so you know why you are doing all three and not just one.

Skill

java-dsa-150

mini-collections

blog post

Pattern recognition

✅ primary

✅ reinforced

Java syntax fluency

Complexity analysis

Data structure internals

✅ primary

Testing discipline (JUnit)

✅ light

✅ primary

Public evidence (recruiter-facing)

✅ primary

Teaching / communication

✅ primary

All three land on your GitHub profile. All three get linked from your LinkedIn. Together they answer the question “has this person actually done the work?” without you having to say a word in the recruiter call.


Order-of-attack warning

Do not start mini-collections before you have solved 40+ LeetCode problems. You need the muscle memory of iteration, generics, and collections usage before you try to reimplement them. Similarly, do not start the blog post before problem 100 — you will have nothing to say. The projects overlap deliberately: java-dsa-150 runs the entire phase, mini-collections slots into weeks 5-7, blog post into weeks 8-9.


Return to README.md · Phase complete → ../03_advanced_java/README.md