Swiggy - SDE 2 - July 2025 [Offer]
Anonymous User
3722
Aug 12, 2025
Aug 12, 2025

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:

  1. Reframe: grid ⇒ graph.
  2. Invariant: each land cell is visited exactly once; once visited, it never contributes to another island.
  3. 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:

  1. Identify the binary decision per element: take or skip.
  2. Define a state that uniquely determines the future: index + sum notion.
  3. Attach memoization to that state.
  4. 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:

  1. Early exit: if n < m * k → -1.
  2. Binary search day range.
  3. 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:

  1. Problem: Ordered, deduplicated event fan-out to inventory & dispatch.
  2. Constraints: Throughput, SLA (<1s p95), ordering by key, back-pressure, visibility.
  3. 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.
  4. Operations: Deploy strategy, SLOs, dashboards, runbooks.
  5. 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

  1. Pattern recognition beats recall. Name the pattern (“connected components”, “binary search on answer”).
  2. Name your invariant. It’s your correctness proof.
  3. Monotonicity is a superpower.
  4. Combine DS wisely.
  5. 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
Comments (7)