"How does that work under the hood?" — the project interview trap
Imagine you're a chef who lists "sous vide cooking" on your CV. When the interviewer asks "how does that work?", saying "I used a water bath" is a weak answer. A strong answer explains the physics: precise temperature control eliminates the guesswork of traditional cooking, because water transfers heat evenly and proteins denature at specific temperatures. Interviewers probe your projects the same way — they want to hear the algorithm under the feature, not just the library name.
🔍 The format for every project algorithm: Idea → DSA primitive → Complexity → The one-paragraph answer. Memorize this structure and you'll never be caught off guard.
Algorithm complexity in your projects at a glance
| Feature | Project | Primitive | Time | Space |
|---|---|---|---|---|
| City twin matching | LandAI | kNN / cosine similarity | O(n·d) brute, O(log n) with FAISS | O(n·d) index |
| XGBoost inference | LandAI | Binary tree traversal (per tree) | O(#trees · depth) | O(model size) |
| TF-IDF ranking | LandAI | Hash maps + sparse dot product | O(total tokens) build, O(nnz) per query | O(vocab size) |
| Urban morphology | LandAI | Grid BFS/DFS (connected components) | O(pixels) | O(pixels) |
| Moving average / EMA | StockVision | Sliding window aggregate | O(n) incremental | O(window size) |
| DCF valuation | StockVision | Discounted sum (prefix product) | O(n) | O(1) |
| Live price tick | StockStump | Hash map O(1) update | O(1) per tick | O(users) |
| Leaderboard ranking | StockStump | Redis ZSET (skip list) | O(log n) update, O(log n + k) range read | O(users) |
Why this matters
When an interviewer says "you mentioned similarity search — how does that work?", they're testing whether you understand the algorithm under your own project. Each item below is: the idea → the DSA primitive → complexity → the one-paragraph answer.
Code: the primitives behind your projects
# kNN cosine similarity — the core of LandAI city-twin matching
import numpy as np
def find_twin_cities(features: np.ndarray, query_idx: int, k: int = 5):
"""
Brute-force cosine kNN: O(n * d) per query.
features: (n_cities, n_features), L2-normalized
Returns indices of k most similar cities (excluding self)
"""
query = features[query_idx] # O(d)
scores = features @ query # O(n * d) — dot product = cosine on L2-normalized
scores[query_idx] = -1 # exclude self
top_k = np.argpartition(scores, -k)[-k:] # O(n) quickselect
return top_k[np.argsort(scores[top_k])[::-1]] # sorted top-k
# Sliding window EMA — the core of StockVision technical indicators
def compute_ema(prices: list, window: int) -> list:
"""Exponential moving average — O(n), O(1) incremental update"""
alpha = 2 / (window + 1) # smoothing factor
ema = []
for i, price in enumerate(prices):
if i == 0:
ema.append(price)
else:
ema.append(alpha * price + (1 - alpha) * ema[-1]) # O(1) per step
return ema
# Leaderboard update — skip list logic (conceptual, implemented via Redis ZSET)
# Redis: ZADD leaderboard <score> <user_id> → O(log n)
# Redis: ZREVRANGE leaderboard 0 9 → O(log n + k) for top 10
// XGBoost-style tree traversal (simplified — what you explain in interviews)
public class DecisionTree {
// Inference: walk from root to leaf — O(depth) per tree
public double predict(TreeNode root, double[] features) {
TreeNode current = root;
while (current.left != null || current.right != null) {
// At each node: check feature threshold and go left or right
if (features[current.featureIndex] <= current.threshold) {
current = current.left;
} else {
current = current.right;
}
}
return current.leafValue; // leaf = prediction contribution
}
// Ensemble: sum of all trees' predictions — O(#trees * depth)
public double predictEnsemble(TreeNode[] trees, double[] features) {
double total = 0;
for (TreeNode tree : trees) {
total += predict(tree, features); // each tree: O(depth)
}
return total; // gradient boosting: sum of residual corrections
}
}
// Grid BFS for urban morphology — same as "Number of Islands"
// Used in LandAI's morphological analysis of urban footprint grids
#include <vector>
#include <queue>
using namespace std;
int countConnectedComponents(vector<vector<int>>& grid) {
int rows = grid.size(), cols = grid[0].size();
int count = 0;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (grid[r][c] == 1) { // unvisited land cell
count++;
// BFS flood fill — O(pixels) total across all components
queue<pair<int,int>> q;
q.push({r, c});
grid[r][c] = 0; // mark visited
int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
while (!q.empty()) {
auto [row, col] = q.front(); q.pop();
for (auto& d : dirs) {
int nr = row + d[0], nc = col + d[1];
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols
&& grid[nr][nc] == 1) {
grid[nr][nc] = 0;
q.push({nr, nc});
}
}
}
}
}
}
return count;
}
Cosine-similarity twin matching (LandAI)
Each city is a feature vector; the "twin" is the nearest neighbour by cosine similarity = dot product of L2-normalized vectors. Brute force is a matrix multiply; FAISS (IVF/HNSW index) makes it sub-linear at scale.
- Primitive: kNN / vector dot product; top-k via
argpartition(quickselect). - Complexity: O(n·d) brute per query; ~O(log n) or better with an index.
Gradient-boosted trees + TreeSHAP (LandAI)
XGBoost is an additive ensemble: each tree corrects the previous trees' residuals (gradient boosting). Inference walks each tree root→leaf. TreeSHAP computes each feature's signed contribution to a prediction (game-theoretic Shapley values, computed efficiently for trees).
- Primitive: binary tree traversal; greedy split selection at train time.
- Complexity: inference O(#trees · depth) per prediction.
TF-IDF infrastructure signals (LandAI)
Turn documents into sparse weighted vectors: term frequency × inverse document frequency down-weights common words. Ranking relevant announcements is then cosine similarity over sparse vectors.
- Primitive: hash maps (term → count/weight), sparse dot product.
- Complexity: O(total tokens) to build; O(nnz) per similarity.
Morphology over urban rasters (LandAI)
scipy.ndimage runs connected-components + dilation/erosion over per-year
footprint grids to measure compactness, fragmentation and growth direction — the
same flood-fill/BFS idea as "number of islands", on an image grid.
- Primitive: grid BFS/DFS (connected components); convolution-style passes.
- Complexity: O(pixels).
Technical indicators & DCF (StockVision)
A moving average / EMA over a price series is a sliding-window aggregate —
O(n) with incremental update rather than recomputing each window. A DCF is a
discounted sum: each future cash flow divided by (1+r)^t, summed.
- Primitive: sliding window; prefix/rolling aggregate.
- Complexity: O(n) for indicators over n bars.
Live price tick & leaderboard (StockStump)
Each price update is O(1) (read price, apply delta, write to Redis). The leaderboard is a sorted set (Redis ZSET) — a skip-list/heap-backed structure giving O(log n) updates and O(log n + k) range reads, instead of re-sorting all users on every change.
- Primitive: hash map (O(1) price), ordered set / skip list (leaderboard).
- Complexity: O(1) tick; O(log n) rank update.
"Twin matching is cosine kNN — O(n·d) brute force, fine at 116 cities; I'd move to a FAISS HNSW index for sub-linear queries at a million." That single sentence shows you know the primitive, the cost, and the upgrade path.
Think it through
PROBLEMAn interviewer asks: 'You built a real-time stock leaderboard. When a user makes a trade and their score changes, how does the leaderboard stay up to date efficiently? Walk me through the data structure choice and its complexity.'
- 1
Naive approach first
“What's the simplest possible implementation, and why is it too slow for real-time?”
- 2
Identify the bottleneck
“Which operation is the bottleneck and what property do we need?”
unlocks after the stage above - 3
The right data structure
“What data structure gives O(log n) update and O(log n + k) range read?”
unlocks after the stage above - 4
State the full answer
“Give the complete interview answer with complexity.”
unlocks after the stage above
Practice — climb the ladder
Climb in order — every rung assumes the one above it. Solve on LeetCode, then tick it here; progress is saved on this device.
Foundation
understand the DSA primitive under each feature- Number of IslandsMedium
BFS flood fill — same primitive as LandAI urban morphology grid analysis.
Sliding window aggregate — same as StockVision's rolling indicators.
Core primitives
the data structures behind your production features- Top K Frequent ElementsMedium
Quickselect / heap — same as kNN top-k in similarity search.
- Design TwitterMedium
Heap of sorted streams — similar to leaderboard's sorted-set requirement.
Quickselect / heap — the primitive behind argpartition in kNN.
Explain at scale
upgrade from O(brute) to production-readyTwo-heap trick — streaming aggregation, same class as rolling indicators.
- LRU CacheMedium
HashMap + doubly-linked list — O(1) operations, same pattern as Redis sorted sets.
Visualize kNN similarity search
Check yourself — algorithms in your projects
1. Your leaderboard re-sorts all users on every trade. What's wrong and what's the fix?
2. LandAI uses cosine similarity to find 'twin cities'. At 116 cities it's O(n·d) brute force. What would you do with 1 million cities?
3. What DSA primitive is used in the morphological analysis of urban footprint grids in LandAI?