AlgoDaily

Practice Problems and Case Studies

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

Your Final Lab

From concepts to decisions

Now that we've covered Arrays and Linked Lists, Stacks and Queues, Trees, Graphs, Hash Tables, Sorting and Searching Algorithms, and Recursion and Dynamic Programming, you're ready for the skill that matters most in interviews and real projects: recognizing which tool fits the situation.

This final lesson is a practice lab. We'll connect common problem signals to data structures, then walk through case studies in JavaScript.

By the end, you should be able to say:

  • What data structure fits this problem?
  • What tradeoff am I accepting?
  • What is the time and space complexity?
  • How do I test edge cases clearly?

Your Final Lab

Problem Solving Loop

A repeatable interview loop

When a problem feels vague, don't jump straight into code. Use this loop:

  1. Restate the goal: What exactly should be returned?
  2. Inspect constraints: How large is the input? Are values sorted? Are duplicates allowed?
  3. Choose a structure: Array, Set, Map, stack, queue, tree, graph, or DP table?
  4. Sketch the algorithm: What changes at each step?
  5. Code the simplest correct version.
  6. Test edge cases: empty input, one item, duplicates, missing values, cycles, deep recursion.
  7. Analyze complexity.

A strong easy/medium solution usually comes from one clear observation, not from memorizing hundreds of problems.

Problem Solving Loop

Case Study: Dedupe

Case study 1: duplicate transaction IDs

Suppose you're given a list of transaction IDs and need to find duplicates.

This is the exact kind of problem where the Hash Tables lesson pays off. We don't need sorting. We need fast membership checks.

Use a Set for IDs we've seen, and another Set for duplicates.

Pattern signal:

  • Need to know if we've seen something before
  • Order is not the main concern
  • Fast lookup matters

That usually points to Set or Map.

```javascript
function findDuplicateIds(ids) {
  const seen = new Set();
  const duplicates = new Set();

  for (const id of ids) {
    if (seen.has(id)) {
      duplicates.add(id);
    } else {
      seen.add(id);
    }
  }

  return [...duplicates];
}

const ids = ['TX100', 'TX200', 'TX100', 'TX300', 'TX200', 'TX400'];
console.log(findDuplicateIds(ids)); // ['TX100', 'TX200']
```

Choose The Tool

You need to process customer support tickets in the exact order they arrive. New tickets go to the back, and agents always take the oldest waiting ticket.

Which data structure best matches this behavior?

Case Study: Window

Case study 2: moving average

Now imagine a dashboard showing the average of the last k stock prices.

This combines ideas from Arrays and Linked Lists and Stacks and Queues: we keep a fixed-size window of recent values, remove the oldest value when the window gets too large, and maintain a running sum.

The key improvement is avoiding repeated summing. Instead of recalculating the whole window every time, update the sum as the window changes.

Pattern signal:

  • Need the most recent k items
  • Oldest item expires first
  • Repeated recalculation would be wasteful
```javascript
function movingAverage(prices, k) {
  const result = [];
  const window = [];
  let sum = 0;

  for (const price of prices) {
    window.push(price);
    sum += price;

    if (window.length > k) {
      sum -= window.shift();
    }

    result.push(Number((sum / window.length).toFixed(2)));
  }

  return result;
}

console.log(movingAverage([10, 20, 30, 40, 50], 3));
// [10, 15, 20, 30, 40]
```

Search Check

True or false: binary search can be applied correctly to any array, even if the values are not sorted.

Case Study: Paths

Case study 3: shortest connection path

Suppose accounts are connected by transfers, referrals, or relationships, and you want the fewest hops from one account to another.

This points back to the Graphs lesson. When every edge has equal cost and you need the shortest number of steps, use breadth-first search.

Pattern signal:

  • Entities are connected to other entities
  • There may be multiple routes
  • Need fewest edges or levels

Use a queue, track visited nodes, and stop when you find the target.

```javascript
function shortestPath(graph, start, target) {
  const queue = [[start, 0]];
  const visited = new Set([start]);

  while (queue.length > 0) {
    const [node, distance] = queue.shift();

    if (node === target) return distance;

    for (const neighbor of graph[node] || []) {
      if (!visited.has(neighbor)) {
        visited.add(neighbor);
        queue.push([neighbor, distance + 1]);
      }
    }
  }

  return -1;
}

const graph = {
  A: ['B', 'C'],
  B: ['D'],
  C: ['E'],
  D: ['F'],
  E: ['F'],
  F: []
};

console.log(shortestPath(graph, 'A', 'F')); // 3
```

Complexity Fill

A function loops through an array of n items once. Inside the loop, it performs only constant-time work.

The time complexity is ____.

Practice Patterns

A compact practice map

Use this as a quick guide when solving easy and medium problems:

Problem signal Likely tool Need fast lookup or dedupe Set / Map Need counts or grouping Map Need last-in, first-out Stack Need first-in, first-out Queue Need sorted search Binary search Need hierarchy traversal Tree traversal Need connected paths Graph BFS / DFS Need repeated subproblems Memoization or tabulation Need all combinations/paths Recursion / backtracking

The point is not to force every problem into a template. The point is to notice the shape of the data and the operation you do most often.

Practice Patterns

Course Wrap Up

What you've built

You've completed the core toolkit for easy and medium data structures and algorithms in JavaScript.

You can now reason about:

  • Storage choices from arrays and linked lists
  • Access order with stacks and queues
  • Hierarchies with trees
  • Relationships with graphs
  • Fast lookup with hash tables
  • Ordered data with sorting and searching
  • Repeated decisions with recursion and dynamic programming

For future practice, focus on explaining your choices out loud:

"I chose this structure because the dominant operation is..."

That sentence is often the difference between guessing and engineering.

Keep practicing with small problems, write tests, compare tradeoffs, and revisit complexity after each solution. That's the learning loop from the first lesson — now with a full toolkit behind it.

Course Wrap Up

Open interactive view →