Swiggy — Backend Engineer (SDE 2) Interview Experience
Month / Year: July 2025
Position: Software Development Engineer II (Backend)
Background: ~3 years in a product-based company, Tier-2 college (2022)
Source
A Senior Talent Partner from Swiggy reached out on LinkedIn. I was scheduled for interviews. It was a three-round elimination track:
- Round 1: DSA buffet (multiple problems, one sitting)
- Round 2: DSA with a design mindset
- Round 3: Bar-raiser — project depth, architecture judgement, PRD→TRD thinking, and behavioural probes
My preparation mantra for all three: know the pattern, explain the intuition, state invariants, and code cleanly while narrating trade-offs.
What follows is the full write-up with extra emphasis on how I thought and how you can think under the same constraints.
Round 1 — DSA Buffet
Problem 1 — Number of Islands
Expectation (what they’re really checking):
Can you recognize a grid problem as a graph problem and quickly deploy a standard traversal with correct visited handling, full edge cases, and clean complexity analysis?
Problem:
Given an m × n grid of '1' (land) and '0' (water), count islands where connections are 4-directional (no diagonals).
How I recognized the pattern (my first 10 seconds):
- “Count groups in a grid” → connected components on an implicit graph.
- Node = cell, Edge = up/down/left/right adjacency.
- The move is flood-fill (DFS or BFS) from every unvisited land cell.
Mental map you can reuse:
- Reframe: grid ⇒ graph.
- Invariant: each land cell is visited exactly once; once visited, it never contributes to another island.
- Plan: scan → on
'1', increment islands and flood-fill to mark the entire component as visited.
Data structures and invariants:
- In-place marking: turn
'1' to '0' during traversal.
- DFS recursion is fine for interview-scale grids; BFS queue if you want to avoid recursion depth.
Complexity:
- Time:
O(mn) — each cell processed once.
- Space:
O(mn) worst-case recursion depth; O(1) aux if BFS with a queue size bounded by mn.
Where people stumble:
- Forgetting to mark visited → double counting.
- Accidentally allowing diagonals.
- Using an expensive
visited[m][n] array when in-place marking is possible.
Advice:
When a prompt says “count groups / regions / islands”, immediately flip to “connected components” and choose a flood-fill.
Say that out loud — it shows you map statements to patterns quickly.
Problem 2 — Count of Subsets With Given Sum
Expectation:
Correctly map to subset-sum, design a memoized recursion, and adapt when the interviewer changes constraints (negative numbers).
Problem:
Count the number of subsets whose sum equals target. Then extend to arrays that may contain negative numbers.
My thought process:
- Non-negative numbers: natural state is
(index, remaining_sum).
A 2D DP table works because remaining_sum stays within [0, target].
- With negatives:
remaining_sum can go below zero and above target unpredictably, so array indexing fails.
Switch to hash-map memoization keyed by (index, current_sum).
Reusable mental map:
- Identify the binary decision per element: take or skip.
- Define a state that uniquely determines the future: index + sum notion.
- Attach memoization to that state.
- Reassess the state model if constraints change.
Complexity:
- Non-negative:
O(n * target) time/space.
- With negatives:
O(n * sum_range) using an unordered_map.
Common pitfalls:
- Treating the negative case with the same DP table → invalid indices.
- Forgetting that the empty subset counts when
target == 0.
Advice:
When constraints change mid-interview, narrate why your previous approach breaks before pivoting.
That’s the difference between memorized and understood.
Problem 3 — Implement a Trie
Expectation:
Clarity on prefix trees, why isEndOfWord exists, and the difference between search and startsWith.
My thought process:
- Trie node must support branching; a single char + pointer = linked list, not a Trie.
isEndOfWord distinguishes a valid word from “just a prefix.”
Mental map:
- Insert: walk or create nodes; mark end at the last node.
- Search: walk nodes; return
isEndOfWord at the last node.
- StartsWith: walk nodes; return true if path exists.
Where people stumble:
- Returning true for
search("app") after only inserting "apple".
- Overcomplicating the node structure.
Advice:
Sketch "app" and "apple" and point to the divergence in isEndOfWord.
Round 2 — DSA with a Design Mindset
Problem A — RandomizedSet
Expectation:
Engineer O(1) insert/remove/random by combining data structures and keep removal constant-time.
Reasoning:
- Uniform getRandom() ⇒ O(1) indexing ⇒ vector.
- O(1) membership/index lookup ⇒ hashmap.
- O(1) remove ⇒ swap victim with tail, pop_back, update map.
Advice:
When one DS can’t satisfy all ops, combine two with complementary strengths and add a constant-time trick.
Problem B — Minimum Days to Make Bouquets of k Adjacent Flowers
Expectation:
Recognize binary search on answer, write a feasibility check, and reason about adjacency.
Restated Problem:
bloomDay[i] = day i-th flower blooms. Need m bouquets, each with k adjacent bloomed flowers. Return min day D possible, else -1.
My thought process:
- Reframe: “By day d, can I make ≥ m bouquets?”
- Convert each flower to usable if
bloomDay[i] ≤ d.
- Count disjoint k-blocks in usable runs.
Key invariant:
Within a usable run length L, max disjoint bouquets = floor(L / k).
Algorithm:
- Early exit: if
n < m * k → -1.
- Binary search day range.
- For each mid day, linearly count bouquets; reset streak on unusable.
Complexity:
O(n log D).
Common mistakes:
- Not resetting streak after counting a bouquet → overlaps.
- Skipping the
n < m*k early check.
Advice:
If feasibility is monotone, binary search the parameter, not the answer space.
Round 3 — Bar-Raiser: Projects, Architecture
Goal:
Assess design judgement, trade-off clarity, and metric anchoring.
My chosen project: Kafka-backed Order Event Processor (Not writing the actual usecase here)
Context:
200k events/min; strict ordering per orderId; at-least-once delivery; idempotent downstream effects.
Story structure:
- Problem: Ordered, deduplicated event fan-out to inventory & dispatch.
- Constraints: Throughput, SLA (<1s p95), ordering by key, back-pressure, visibility.
- Decisions:
- Partition by orderId for sequencing.
- Redis idempotency keys.
- Two-tier retries; DLQ for poison events.
- At-least-once + idempotency over exactly-once for simplicity.
- Operations: Deploy strategy, SLOs, dashboards, runbooks.
- Impact: -40% missed updates, -300ms latency.
Behavioural Qs:
- Bias for Action: Thin TRD slice with feature flags to unblock.
- Dive Deep: Refactor if ≤30% cost of rewrite; else rewrite behind adapter.
- Disagree & Commit: Accepted alternate sharding; optimized it later.
Technical Desgining:
- Extract explicit/implied requirements.
- Model entities, invariants, life-cycles.
- Define API contracts + idempotency rules.
- Design storage: partitioning, indexes, constraints.
- Decide consistency model.
- Plan observability (RED metrics, traces, logs).
- Scalability strategy.
- Operational readiness & runbooks.
- Stakeholder review & risk mitigation.
Closing Takeaways
- Pattern recognition beats recall. Name the pattern (“connected components”, “binary search on answer”).
- Name your invariant. It’s your correctness proof.
- Monotonicity is a superpower.
- Combine DS wisely.
- Own the why. Numbers without reasons are noise.
Verdict
Got the offer.
- Round 1: Speed + clarity in DSA
- Round 2: Feasibility reasoning + DS choice
- Round 3: Depth in design + behavioural alignment