Readplace

Learn Algorithms for Interviews, Forget Them for Work

fagnerbrack.com 6 min read
View original
  • current
Summary (TL;DR)
Algorithm interviews test narrow skills like reversing a linked list, which rarely appear in production work. Real problems involve messy inputs, tradeoffs, and design decisions like deduplication in a sliding window without bounded memory. The author describes building a UI for Sabre GDS integration instead of a full automated build, shipping value incrementally. They argue that interview skills and production skills are mismatched, and propose honest recognition that algorithms are a credential, not a measure of engineering ability.

Learn Algorithms for Interviews, Forget Them for Work

Reversing a linked list in place is a famous interview question. It tests pointer manipulation, edge cases, and step-by-step reasoning about mutation. It rarely comes up in production work.

I studied it too. I passed and failed interviews using it only to never touch it again 😄.

Production code doesn't use linked lists. It uses arrays, hash maps, queues backed by ring buffers, and whatever the standard library hands you. The last time I needed to reverse a sequence at work, I called .reverse() and nobody reviewed it. Sometimes you don't even need to write code.

The gap between interview skill and production skill is not a calibration error, it's a category mismatch. Developers spend years inside that mismatch without naming it.

The proof is in the specifics. You sit in a 45-minute interview. The interviewer asks you to reverse a singly linked list in place. You walk through three pointers: prev, current, next.

You handle the null case and you get the offer:

function reverseList(head: ListNode | null): ListNode | null {
let prev: ListNode | null = null;
let current = head;
while (current !== null) {
const next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}

Linked lists thrive in places like the Linux kernel, where memory layout and intrusive structures matter. Application code is a different world. The data structure rarely shows up there.

Arrays dominate for simple reasons: memory locality, O(1) indexing, and battle-tested standard library implementations. Linked lists survive in textbooks, in system-level edge cases, and in interview prep.

Now take a real production problem. You have a stream of events from multiple sources, some of them duplicates. You need to deduplicate them within a five-minute sliding window without unbounded memory growth.

This problem is common. Event-driven architectures hit it weekly.

Here is a first pass at what that looks like:

const seen = new Map<string, number>();
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const WINDOW_MS = 5 * MINUTE;

const isDuplicate = (event: StreamEvent): boolean => {
const now = Date.now();
for (const [key, timestamp] of seen) {
if (now - timestamp > WINDOW_MS) seen.delete(key);
}
if (seen.has(event.id)) return true;
seen.set(event.id, now);
return false;
}

This code has visible problems: the cleanup loop is O(n) on every call and there is no cap on map size.

The dedup key assumes event.id is stable across sources, which often is not.

Those are the right problems to have. They are design decisions, not puzzle answers. No LeetCode problem prepares you for them.

The interview canon barely touches this, it has sliding window problems, but they operate on static arrays with known bounds. The production version has no known bounds and a clock that drifts.

The problems you study for interviews have clean inputs and single correct outputs. The problems you solve at work have dirty inputs and acceptable tradeoffs

Early-career developers hear this often: study LeetCode for interviews, it works. The system rewards it, so fighting the system costs more than playing along.

But do not confuse passing the test with learning the trade! What builds engineering skill is not the study plan, it's the real life work. You read other people’s code, the kind that survived three years of patches and ownership changes. You debug a bug whose symptoms appear two services away from the cause. You ship a system and you watch it break in ways you did not predict.

A startup I advised wanted to automate flight ticketing through Sabre GDS. Sabre’s API is notoriously a hell to parse: there are refs in one part of the response, ids in another and you need to know which one refers to which to build the full itinerary. Full automation and ZERO previous travel domain expertise meant six months of work and cash they did not have.

The textbook move was a full scoped build with a release at the end. That path meant six months of silence followed by something the team had to trust worked as intended.

I took a different route. Instead of integrating the whole automation in the existing spaguetti legacy system with no tests, I built a UI for the travel operation team that was a plain HTML forms with multiple pages. The server handled the Sabre call and rendered the results so they could create the record using next-next-finish instead of 10 minutes of weird travel agent command line interface lingo:

// Server-side page handler
export async function render(query: URLSearchParams) {
const sabreQuery = buildSabreQuery(query);
const response = await sabre.post('/v5/shop/flights', sabreQuery);
return renderTemplate({ flights: parseSabreResponse(response) });
}

Travel operations team used it from day one and every call with them surfaced a gap. parseSabreResponse learned how to add more than one adult passenger. buildSabreQuery gained a new parameter. The parsing logic grew one real case at a time.

The automation sat alongside manual work. Itineraries the UI could handle went through the API. The rest went manually through Sabre’s CLI like before.

We prioritised the routes with the most bookings first. The manual work shrank week by week.

Here is the part the textbook plan misses: revenue climbed during the build itself. Every automated route freed operator time. That freed time allowed marketing budget to increase. The tradeoff was honest. The overall path took longer than a planned build. But every day shipped something that generate real value, as in cash value. After all, time is money.

Instead of 80% of nothing, we had 100% of something. The "something" kept growing

That parsing logic became the foundation of the full automated platform months later. The travel operators trusted it because they helped shape it instead of sitting in a room to produce a huge system where they only used 20% of. That solution was not only a coding solution. It was a reading of the business, the team, and what mattered for THEIR context.

A pure coder starts with the API integration. Six months of silence follow. A pure product manager without code takes weeks to approve the scope. An engineer or PM who can do both ships something on day one. The companies that stall are the ones who split those skills across two people.

The harder problem is on the other side of the career ladder.

I have reviewed code from candidates who completed hard dynamic programming problems in the interview. Their production code had no error handling. Functions ran 200 lines long. They practiced what the system measured, and the system measured useless puzzle-solving.

The fix is not to abolish algorithm interviews. Removing them creates worse problems: vague culture-fit screens, trivia questions, endless calls, or take-home projects that eat 20 hours of unpaid labor.

Some companies have found a middle ground. I went through all stages of Canva's interview process. The problems felt like production work: messy inputs, using AI to guide implementation on your terms, tradeoffs with no clean answer, code that had to be readable by someone else, and technical and teamwork conversations with actual real life communication scenario.

It was not perfect, but closer to the job than any whiteboard session I have sat through in companies of the same size.

The fix is honesty. Algorithm interviews measure a narrow, trainable skill that correlates weakly with production performance and strongly with hours spent on LeetCode.

Admit that, and candidates stop treating a blank on Dijkstra’s algorithm as proof they are bad engineers. Interviewers stop treating a clean medium-hard result as proof they found a great one.

Knowing algorithms is a credential.

Using them is a craft.

If you liked this, you might like readplace.com, built for exactly this kind of reading.

Thanks for reading. If you have some feedback, reach out to me on LinkedIn, Github or by replying to this post.