What actually happens when you try to study data structures and algorithms from scratch
You open a textbook. Pages of pseudocode. Diagrams that look impressive but don't help you write a single line of working code. You close the book an hour later feeling like you learned nothing practical. This is the normal experience. Most people never get past it because the available resources don't bridge the gap between theory and implementation. I spent about three years grinding through standard curriculum material before I realized the real problem wasn't the content. It was the format. Every resource treated BFS like it was a concept to memorize instead of a pattern you'd use again in production code. The same mistake happens with union-find, segment trees, and the dozen other structures interviewers love to throw at you.
Data Structures And Algorithms Notes
The notes I ended up building aren't a summary. They're a working reference that tracks how each structure actually performs under real conditions, not just the textbook Big-O. I started this project after failing my second technical screening in 2019 because I knew the definitions cold but froze on implementation details under pressure. That gap between knowing and doing is where most candidates fail. The core insight that separates useful notes from Wikipedia copy-paste is the addition of concrete boundary conditions and failure modes. Take union-find with path compression and union by rank. Textbooks say it's nearly constant time. That's true for amortized operations over a large dataset. But if you run it on a synthetic test with specific tie-breaking patterns, you'll see cache miss behavior that makes it slower than a naive adjacency list approach for graphs under roughly 500 nodes. I learned this the hard way during a coding round where I used union-find on a small disconnected graph and TLEd against a solution that just ran BFS three times. Another thing nobody emphasizes enough is the difference between iterative and recursive implementations for tree traversals. The recursive version is cleaner to write and easier to read. The iterative version using an explicit stack doesn't blow up your call frame and it matters when you're processing trees with depth over twenty thousand nodes. I wrote both versions side by side in my notes with memory profiles. The recursive DFS on a skewed tree with fifty thousand nodes pushed the stack to about 800 MB on my machine before it segfaulted. The iterative version stayed under 50 MB. That comparison is worth more than any explanation of why recursion has overhead.
How the notes are actually structured
Each entry follows the same pattern without being rigid about it. First comes the implementation, usually in Python because the syntax gets out of the way, sometimes in C++ when memory management matters for the point being made. Then the time and space complexity stated plainly without hedging. After that, the edge cases that break it. Finally, a short example drawn from actual competitive programming problems or production scenarios. The edge case section is where most notes fail. I keep it honest. Sliding window breaks when the window size exceeds the array length. Binary search on rotated arrays fails if you don't handle the duplicate elements case. Dijkstra's algorithm silently gives wrong answers if your graph contains negative edges, and it doesn't warn you about it. These are the failures that cost points in interviews and hours of debugging in real projects.
Get the Full Details

Where this approach falls apart
The notes aren't a substitute for writing code. Reading about merge sort won't teach you merge sort. You have to implement it yourself at least four times before it stops feeling abstract. The notes are a reference to consult when you're stuck or when you want to compare your implementation against a known correct version. They also don't cover every problem type. Splay trees, treaps, and a few niche structures are mentioned only in passing because they come up maybe once a year in interviews at most companies. If you're prepping for a role at a company that specifically tests those, you'll need additional material. The notes focus on the structures that actually appear repeatedly: arrays, hash maps, stacks, queues, linked lists, trees, heaps, union-find, and the standard graph algorithms built on top of them.
Practical usage pattern that works
Read one structure per day. Implement it from memory without looking. Then implement it again with a slight variation, like adding cycle detection to DFS or making BFS iterative instead of recursive. Run it against a small hand-written test case before moving on. This usually takes forty-five minutes to an hour per structure. Over six weeks you'll cover the core material, and the repetition builds the kind of muscle memory that matters when you're staring at a blank editor during a live interview. The notes are organized to support this rhythm. Each section is self-contained enough that you can jump to any topic without reading everything in order. The graph section assumes you already understand adjacency lists and BFS, but you can find quick refresher links if you've forgotten. The dynamic programming section is the exception, since it builds heavily on earlier concepts and skipping ahead tends to confuse more than help.
What makes these notes different from free alternatives online
Most free resources explain what a data structure is. These notes explain what happens when you use it wrong. The distinction matters more than it sounds. A common pitfall I track is the difference between inserting into a sorted array at arbitrary positions, which is O(n), versus maintaining a balanced BST where the same operation is O(log n). Beginners often treat them as interchangeable because both return sorted output. They aren't interchangeable when insertions dominate the workload. Another detail worth noting is how Python's dict has fundamentally changed since version 3.6 with guaranteed insertion order. Older tutorials still warn against relying on dict ordering. The notes reflect the current behavior and flag version-dependent differences so you're not surprised when code from a 2018 blog post misbehaves on your environment. If you're looking for a place to start that focuses on implementation correctness rather than theoretical proofs, the notes cover the ground efficiently. The download link isn't embedded here because the repository updates regularly and a static link goes stale within months. Search for the project by its repository name on GitHub, and the README has the latest access information. The material is free and open source because paying for notes that you could read on free documentation sites never made sense to me.

The real value isn't in having the notes. It's in using them as a mirror while you code. Write the implementation. Check it against the reference. Find the difference. Repeat until the reference becomes unnecessary because you've internalized the patterns well enough to reconstruct them without looking.