20 System-Thinking DSA Problems
📖 Concept
These problems bridge the gap between coding interviews and system design. They ask: "How would you use DSA to solve a real-world problem at scale?"
The 20 System-Thinking Problems:
Data Processing (1-5):
- Design a hit counter that counts hits in the past 5 minutes (circular buffer)
- Design a log aggregator that finds the top K most frequent error messages (hash map + heap)
- Design a stream processor that finds the median of incoming numbers (two heaps)
- Design a deduplication system for real-time event processing (bloom filter + hash set)
- Design a moving average calculator from a data stream (queue)
System Components (6-10): 6. Design an autocomplete system with personalized suggestions (trie + user history) 7. Design a URL shortener with analytics (base62 encoding + hash map) 8. Design a rate limiter that supports multiple tiers (token bucket per tier) 9. Design a notification system that respects user preferences (priority queue + graph) 10. Design a task scheduler with dependencies (topological sort + priority queue)
Real-time Systems (11-15): 11. Design a real-time leaderboard that updates with new scores (balanced BST or skip list) 12. Design a stock ticker that shows min/max/avg in a sliding window (monotonic deque) 13. Design a feed ranking system for social media (graph + priority queue) 14. Design a spell checker with suggestions (trie + edit distance) 15. Design a location-based search (find nearest restaurants) (quadtree or geohash)
Infrastructure (16-20): 16. Design a consistent hashing ring for load balancing (sorted map + binary search) 17. Design a distributed cache eviction policy (LRU/LFU + replication) 18. Design a file system with path operations (trie of directory names) 19. Design an undo/redo system for a text editor (stack of operations) 20. Design a garbage collector using reference counting and mark-sweep (graph traversal)
Each problem requires choosing the RIGHT data structure and algorithm for the constraints.
💻 Code Example
1// PROBLEM 1: HIT COUNTER — Count hits in last 5 minutes2class HitCounter {3 constructor() {4 this.hits = new Array(300).fill(0); // 5 min = 300 sec5 this.times = new Array(300).fill(0);6 }78 hit(timestamp) {9 const idx = timestamp % 300;10 if (this.times[idx] !== timestamp) {11 this.times[idx] = timestamp;12 this.hits[idx] = 1;13 } else {14 this.hits[idx]++;15 }16 }1718 getHits(timestamp) {19 let total = 0;20 for (let i = 0; i < 300; i++) {21 if (timestamp - this.times[i] < 300) total += this.hits[i];22 }23 return total;24 }25}2627// PROBLEM 7: URL SHORTENER28class URLShortener {29 constructor() {30 this.urlToCode = new Map();31 this.codeToUrl = new Map();32 this.counter = 0;33 }3435 encode(longUrl) {36 if (this.urlToCode.has(longUrl)) return this.urlToCode.get(longUrl);37 const code = this.toBase62(this.counter++);38 this.urlToCode.set(longUrl, code);39 this.codeToUrl.set(code, longUrl);40 return 'http://tiny.url/' + code;41 }4243 decode(shortUrl) {44 const code = shortUrl.split('/').pop();45 return this.codeToUrl.get(code);46 }4748 toBase62(num) {49 const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';50 if (num === 0) return '0';51 let result = '';52 while (num > 0) { result = chars[num % 62] + result; num = Math.floor(num / 62); }53 return result;54 }55}5657// PROBLEM 16: CONSISTENT HASHING58class ConsistentHash {59 constructor(numReplicas = 3) {60 this.replicas = numReplicas;61 this.ring = new Map(); // hash → server62 this.sortedKeys = [];63 }6465 hash(key) {66 let h = 0;67 for (let i = 0; i < key.length; i++) h = (h * 31 + key.charCodeAt(i)) & 0x7fffffff;68 return h;69 }7071 addServer(server) {72 for (let i = 0; i < this.replicas; i++) {73 const h = this.hash(server + ':' + i);74 this.ring.set(h, server);75 this.sortedKeys.push(h);76 }77 this.sortedKeys.sort((a, b) => a - b);78 }7980 getServer(key) {81 const h = this.hash(key);82 for (const k of this.sortedKeys) {83 if (k >= h) return this.ring.get(k);84 }85 return this.ring.get(this.sortedKeys[0]); // Wrap around86 }87}8889// PROBLEM 19: UNDO/REDO90class UndoRedo {91 constructor() { this.undoStack = []; this.redoStack = []; this.state = ''; }9293 execute(operation) {94 this.undoStack.push(this.state);95 this.state = operation(this.state);96 this.redoStack = []; // Clear redo after new action97 }9899 undo() {100 if (this.undoStack.length === 0) return;101 this.redoStack.push(this.state);102 this.state = this.undoStack.pop();103 }104105 redo() {106 if (this.redoStack.length === 0) return;107 this.undoStack.push(this.state);108 this.state = this.redoStack.pop();109 }110}
🏋️ Practice Exercise
Challenge: Design each system with:
- Choose the right data structure — explain WHY
- Define the API (methods with params and return types)
- Analyze time and space complexity for each operation
- Consider edge cases and failure modes
- How would you scale it to handle 1 million users?
Pick 5 problems this week and implement them. For each:
- Write the code
- Test with example scenarios
- Discuss scaling considerations
- Identify which DSA concepts are being applied
⚠️ Common Mistakes
Choosing the wrong data structure — always start by listing the operations needed and their frequency
Not considering scalability — solutions that work for 100 users may fail at 1M users
Over-engineering — start simple, then iterate with optimizations
Ignoring space complexity — in system design, memory is a real constraint
Not discussing trade-offs — every design has pros and cons; mention them
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for 20 System-Thinking DSA Problems