Mastercard Previous Year Coding Questions
Mastercard hires Software Engineers through campus drives, internships, and off-campus applications, with a large engineering presence in Pune and other Indian tech centers, working on payment processing, fraud detection, and core transaction infrastructure. The process has a strong backend focus (frequently around Java/Spring Boot) and, compared to pure product companies, leans less on obscure algorithm tricks and more on practical problem-solving, clear communication, and how you reason about tradeoffs. System design rounds are consistently shaped by the payments domain, expect fraud detection, batch transaction processing, and payment gateway scalability to come up in nearly every design conversation.
Hiring Process
Step 1: Recruiter Screen A casual 30-minute intro call covering your background, comfort with the Java/Spring Boot stack, and salary expectations.
Step 2: Online Assessment Either a 60–90 minute automated coding test on HackerRank or Codility with 2–3 problems focused on strings, arrays, and basic data structures, or (for some tracks) a live technical screen with a senior engineer instead of an automated test.
Step 3: Technical Round 1 DSA-focused, typically 2 coding problems at easy-to-medium difficulty. Less about tricky optimisations, more about correct, clean code and clearly explaining your reasoning and edge-case handling.
Step 4: Technical Round 2 Goes deeper into practical engineering judgment: design tradeoff questions, project discussions, and live coding, sometimes an object-oriented design discussion with follow-up requirement changes mid-interview.
Step 5: Managerial / Behavioural Round Discussion of your past projects, how you work in a team, and situational questions.
Step 6: HR Round Compensation, offer details, and culture fit.
Tips: Mastercard's coding rounds reward clean, correct, well-explained solutions over clever one-liners, prioritise readability and edge-case handling over cleverness. For System Design, always frame your answer through a payments lens, if a design question doesn't obviously mention fraud, money movement, or transaction consistency, the interviewer is still listening for how your design would handle those concerns.
Preparation Resources
Part 1 — OA Questions
1. Valid Anagram Easy
Given two strings s and t, return true if t is an anagram of s (uses exactly the same characters with the same frequency).
Input: s = "anagram", t = "nagaram"
Output: true
Input: s = "rat", t = "car"
Output: false
Approach: Count character frequencies of s in an array/HashMap, then decrement for each character of t. If all counts return to zero and lengths matched, it is an anagram.
Complexity: Time O(n) · Space O(1) (fixed alphabet size)
Follow-up: What if the strings contain unicode characters instead of just lowercase English letters?
2. Missing Number Easy
Reported as a "missing element in a sequence" question. Given an array containing n distinct numbers from 0 to n, return the one number missing from the range.
Input: nums = [3,0,1]
Output: 2
Input: nums = [9,6,4,2,3,5,7,0,1]
Output: 8
Approach: Compute the expected sum of 0..n using the formula n*(n+1)/2, subtract the actual sum of the array, the difference is the missing number. XOR-based approach also works and avoids overflow.
Complexity: Time O(n) · Space O(1)
Follow-up: Solve it using XOR instead of sum, and explain why XOR avoids a potential overflow issue.
3. Middle of the Linked List Easy
Given the head of a singly linked list, return the middle node. If there are two middle nodes, return the second one.
Input: head = [1,2,3,4,5]
Output: [3,4,5]
Input: head = [1,2,3,4,5,6]
Output: [4,5,6]
Approach: Slow/fast pointer technique: slow moves one step, fast moves two steps. When fast reaches the end, slow is at the middle.
Complexity: Time O(n) · Space O(1)
Follow-up: Return the first middle node instead when the list has even length.
4. Count Primes Medium
Reported as "print all prime numbers from 1 to n". Given an integer n, return the number of prime numbers strictly less than n.
Input: n = 10
Output: 4
Explanation: 2, 3, 5, 7 are the primes less than 10.
Approach: Sieve of Eratosthenes: create a boolean array marking composites. For each prime p starting from 2, mark all multiples of p as composite. Count the remaining unmarked numbers.
Complexity: Time O(n log log n) · Space O(n)
Follow-up: Modify the sieve to also print (not just count) every prime up to n.
5. Cells with Adjacent 1s in a Binary Matrix Medium
A GfG-style question reported in the OA. Given a binary matrix of 0s and 1s, count the number of cells that have at least one adjacent (4-directional) cell equal to 1.
Input: matrix = [[1,0,0],[0,1,0],[0,0,1]]
Output: 2
Explanation: cells (0,1) and (1,0) are each adjacent to the 1 at (0,0)/(1,1), similarly for the other diagonal pairs; exact count depends on full adjacency.
Approach: Iterate every cell. For each cell, check its up to 4 neighbours (bounds-checked); if any neighbour is 1, increment the count for that cell (count the cell itself once, regardless of how many 1-neighbours it has).
Complexity: Time O(rows * cols) · Space O(1) extra
Follow-up: What if adjacency should also include the 4 diagonal directions (8-directional)?
6. Valid Lexicographical Pairs Count Medium
Reported in the OA. Given a string of words separated by whitespace, for each word count the number of adjacent character pairs that are in non-decreasing lexicographical order, and return the total across all words.
Input: s = "ab ba cab"
Output: 3
Explanation: "ab" has 1 valid pair (a<=b), "ba" has 0, "cab" has 1 valid pair (a<=b); totals depend on exact adjacency rule, illustrative here.
Approach: Split the string on whitespace. For each word, scan adjacent character pairs and increment a counter whenever word[i] <= word[i+1]. Sum counts across all words.
Complexity: Time O(n) · Space O(1) extra
Follow-up: What if pairs must be strictly increasing instead of non-decreasing?
Part 2 — Phone Screen Questions
7. Linked List Cycle Easy
Given the head of a linked list, determine if the linked list has a cycle.
Input: head = [3,2,0,-4], pos = 1 (tail connects to index 1)
Output: true
Approach: Floyd's cycle detection: slow pointer moves one step, fast pointer moves two steps. If they ever meet, a cycle exists. If fast reaches null, no cycle.
Complexity: Time O(n) · Space O(1)
Follow-up: Find the exact node where the cycle begins (Linked List Cycle II).
8. Second Largest Element in an Array Easy
A frequently reported Mastercard question. Given an array of integers, find the second largest distinct element without sorting the array.
Input: arr = [12,35,1,10,34,1]
Output: 34
Input: arr = [10,10,10]
Output: -1 (no second distinct largest)
Approach: Single pass tracking the largest and second-largest values seen so far. When a new number exceeds the current largest, the old largest becomes the new second-largest. Skip duplicate values equal to the current largest.
Complexity: Time O(n) · Space O(1)
Follow-up: Generalise this to find the Kth largest distinct element in a single pass.
9. Make Array Palindromic with One Merge Medium
Reported as 'make the array palindromic by adding one more adjacent element'. Given an array, determine if it can be made into a palindrome by merging (summing) exactly one pair of adjacent elements, and return the resulting array if so.
Input: arr = [1,2,3,3]
Output: [1,5,3]
Explanation: Merging arr[1] and arr[2] (2+3=5) gives [1,5,3], which is a palindrome.
Approach: Two pointers from both ends. When values mismatch, try merging the smaller side with its inward neighbour (sum them) and re-compare, since merging can only be done once, track whether a merge has already been used.
Complexity: Time O(n) · Space O(n) for the result array
Follow-up: What if you are allowed up to K merges instead of exactly one?
10. Caesar Cipher String Encryption Medium
Reported as 'string manipulation involving encryption with a given key'. Given a string and a shift key, encrypt the string by shifting each letter forward by the key amount, wrapping around the alphabet.
Input: s = "xyz", key = 3
Output: "abc"
Approach: For each character, compute its position in the alphabet, add the key, and take modulo 26 to wrap around, then convert back to a character. Preserve case and skip non-alphabetic characters.
Complexity: Time O(n) · Space O(n) for the result
Follow-up: Write the corresponding decryption function, and discuss why Caesar cipher is cryptographically weak (frequency analysis).
11. Lowest Common Ancestor from Root Paths Medium
Reported with a path-array framing: given a binary tree and the root-to-node path strings for two nodes, find their lowest common ancestor.
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Approach: Recursive DFS: if the current node is p or q, or p and q are found in different subtrees, the current node is the LCA. Otherwise recurse into whichever subtree contains both. If given as explicit root-to-node paths instead, find the last common node in both path sequences.
Complexity: Time O(n) · Space O(h)
Follow-up: Solve it when nodes carry a parent pointer instead of starting DFS from the root.
12. Find Duplicate Transactions in a Time Window Medium
A fintech-flavoured SQL question reported at Mastercard. Given a transactions table (transaction_id, account_id, amount, transaction_time), write a query to find transactions from the same account with the same amount occurring within 60 seconds of each other (likely duplicate charges).
Table: transactions(transaction_id, account_id, amount, transaction_time)
Find all (transaction_id) pairs where account_id and amount match and transaction_time differs by <= 60 seconds.
Approach: Self-join the transactions table on account_id and amount where t1.transaction_id < t2.transaction_id, filtering on ABS(TIMESTAMPDIFF(SECOND, t1.transaction_time, t2.transaction_time)) <= 60. A window function approach (LAG() partitioned by account_id and amount, ordered by transaction_time) avoids the self-join's O(n^2) blowup on large tables.
Complexity: Self-join: O(n^2) in the worst case · Window function: O(n log n) for the sort
Follow-up: Rewrite the query using LAG() instead of a self-join, and explain why it scales better on large transaction tables.
13. Two Sum Easy
Given an array of integers and a target, return indices of the two numbers that add up to target.
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Approach: HashMap of value → index, checking for the complement before inserting each number.
Complexity: Time O(n) · Space O(n)
Follow-up: Solve it in O(1) space if the array is already sorted.
Part 3 — Onsite Questions
14. Reverse Linked List Easy
Given the head of a singly linked list, reverse the list and return the new head.
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]
Approach: Iterate with three pointers (prev, curr, next), reversing the curr.next link at each step and advancing all three.
Complexity: Time O(n) · Space O(1)
Follow-up: Reverse only a sublist between positions left and right (Reverse Linked List II).
15. Merge Two Sorted Lists Easy
Merge two sorted linked lists into one sorted list by splicing the nodes together.
Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4]
Approach: Use a dummy head node. Compare the current nodes of both lists, attaching the smaller each time, then attach whatever remains of the non-exhausted list.
Complexity: Time O(m + n) · Space O(1)
Follow-up: Merge k sorted lists instead of just two (Merge k Sorted Lists).
16. Linked List Cycle II Medium
Given the head of a linked list, return the node where the cycle begins, or null if there is no cycle.
Input: head = [3,2,0,-4], pos = 1
Output: node at index 1
Approach: Floyd's algorithm: find the meeting point of slow/fast pointers first. Then reset one pointer to head and advance both one step at a time, they meet exactly at the cycle's start.
Complexity: Time O(n) · Space O(1)
Follow-up: Prove why resetting one pointer to head and advancing both by one step finds the cycle start (the math behind it).
17. Binary Search Easy
Given a sorted array of integers and a target, return its index, or -1 if not found, in O(log n) time.
Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Approach: Standard binary search: compare target to the middle element, narrowing the search range by half each time.
Complexity: Time O(log n) · Space O(1)
Follow-up: Find the first and last occurrence of target if duplicates are allowed.
18. Search in Rotated Sorted Array Medium
Given a rotated sorted array with distinct values and a target, return the index of target, or -1, in O(log n) time.
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Approach: Modified binary search: at each step determine which half is properly sorted, then check if the target lies within that half to decide which side to recurse into.
Complexity: Time O(log n) · Space O(1)
Follow-up: Handle duplicate values in the array.
19. Kth Largest Element in an Array Medium
Given an integer array and k, return the kth largest element.
Input: nums = [3,2,1,5,6,4], k = 2
Output: 5
Approach: Min-heap of size k, or quickselect for average O(n).
Complexity: Time O(n log k) or O(n) average · Space O(k)
Follow-up: What if the array is a live stream of incoming transaction amounts?
20. Top K Frequent Elements Medium
Given an integer array and k, return the k most frequent elements.
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Approach: HashMap for frequency counts, then a min-heap of size k or bucket sort by frequency.
Complexity: Time O(n log k) or O(n) with bucket sort · Space O(n)
Follow-up: Adapt this to find the top K most frequent merchant categories in a transaction stream.
21. Longest Substring Without Repeating Characters Medium
Given a string, find the length of the longest substring without repeating characters.
Input: s = "abcabcbb"
Output: 3
Approach: Sliding window with a HashMap of last-seen index per character, jumping the left pointer past repeats.
Complexity: Time O(n) · Space O(min(n, charset))
Follow-up: Return the actual substring, not just its length.
22. Group Anagrams Medium
Given an array of strings, group the anagrams together.
Input: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
Approach: Compute a canonical key (sorted characters or a character-count signature) per string, and group by key in a HashMap.
Complexity: Time O(n * k log k) · Space O(n * k)
Follow-up: Use character counts instead of sorting for O(n * k).
23. Number of Islands Medium
Given a 2D binary grid, return the number of islands (connected groups of land).
Input: grid = [["1","1","0","0"],["1","1","0","0"],["0","0","1","0"],["0","0","0","1"]]
Output: 3
Approach: DFS/BFS from every unvisited land cell, marking the connected component visited.
Complexity: Time O(rows * cols) · Space O(rows * cols)
Follow-up: Solve it using Union-Find instead.
24. Course Schedule Medium
Given numCourses and prerequisite pairs, determine if it is possible to finish all courses (no cycle).
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Approach: Kahn's algorithm (BFS): process nodes with in-degree 0, decrement neighbours. If all nodes processed, no cycle.
Complexity: Time O(V + E) · Space O(V + E)
Follow-up: Return a valid course order instead of just true/false.
25. LRU Cache Medium
Design a Least Recently Used cache supporting get(key) and put(key, value), both O(1).
capacity = 2; put(1,1); put(2,2); get(1) → 1; put(3,3) evicts key 2
Approach: HashMap (key → node) combined with a doubly linked list ordered by recency.
Complexity: Time O(1) per operation · Space O(capacity)
Follow-up: Design an LFU cache instead.
26. Merge Intervals Medium
Given an array of intervals, merge all overlapping intervals.
Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Approach: Sort by start time, merge the current interval into the last merged one if overlapping.
Complexity: Time O(n log n) · Space O(n)
Follow-up: Insert a new interval into an already-sorted, non-overlapping list efficiently.
27. Validate Binary Search Tree Medium
Given the root of a binary tree, determine if it is a valid BST.
Input: root = [5,1,4,null,null,3,6]
Output: false
Approach: Recursive DFS carrying a valid (min, max) range for each node, narrowing the range for each subtree.
Complexity: Time O(n) · Space O(h)
Follow-up: Do it via inorder traversal, checking strictly increasing values.
28. Binary Tree Level Order Traversal Medium
Given the root of a binary tree, return the level order traversal of its nodes' values.
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]
Approach: BFS using a queue, processing one full level at a time by tracking the queue size at the start of each level.
Complexity: Time O(n) · Space O(n)
Follow-up: Return the zig-zag level order traversal instead.
29. Word Break Medium
Given a string s and a dictionary wordDict, return true if s can be segmented into dictionary words.
Input: s = "leetcode", wordDict = ["leet","code"]
Output: true
Approach: dp[i] = true if s[0..i) is segmentable, checking every split point j < i.
Complexity: Time O(n^2) · Space O(n)
Follow-up: Return all possible segmentations (Word Break II).
30. Coin Change Medium
Given coin denominations and a target amount, return the fewest coins needed, or -1 if impossible.
Input: coins = [1,2,5], amount = 11
Output: 3
Approach: dp[i] = min coins for amount i, trying every coin at each amount.
Complexity: Time O(amount * coins) · Space O(amount)
Follow-up: Return the number of distinct combinations instead (Coin Change II).
31. Longest Common Subsequence Medium
Given two strings, return the length of their longest common subsequence.
Input: text1 = "abcde", text2 = "ace"
Output: 3
Approach: 2D DP where dp[i][j] = LCS of text1[0..i) and text2[0..j).
Complexity: Time O(m * n) · Space O(m * n)
Follow-up: Reconstruct the actual subsequence string.
32. Subsets Medium
Given an array of unique integers, return all possible subsets.
Input: nums = [1,2,3]
Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
Approach: Backtracking: at each index branch into include/exclude.
Complexity: Time O(2^n) · Space O(2^n)
Follow-up: Handle duplicate values without duplicate subsets.
33. Permutations Medium
Given an array of distinct integers, return all possible permutations.
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Approach: Backtracking with a used array, trying every unused number at each level.
Complexity: Time O(n * n!) · Space O(n!)
Follow-up: Handle duplicate values (Permutations II).
34. 3Sum Medium
Given an integer array, return all unique triplets summing to zero.
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Approach: Sort the array, then two pointers per fixed first element, skipping duplicates.
Complexity: Time O(n^2) · Space O(1) excluding output
Follow-up: Solve 4Sum with an extra outer loop.
35. Trapping Rain Water Hard
Given an elevation map, compute how much water it can trap after raining.
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Approach: Two pointers tracking max height from each side, moving the pointer with the smaller max inward.
Complexity: Time O(n) · Space O(1)
Follow-up: Solve the 2D version using a priority queue.
36. Product of Array Except Self Medium
Given an array, return an array where each element is the product of all elements except itself, without division.
Input: nums = [1,2,3,4]
Output: [24,12,8,6]
Approach: Prefix-product pass followed by a suffix-product pass, combined into the output array.
Complexity: Time O(n) · Space O(1) extra excluding output
Follow-up: Handle zeros in the array without special-casing them.
37. Valid Parentheses Easy
Given a string of brackets, determine if it is valid.
Input: s = "()[]{}"
Output: true
Approach: Stack: push opening brackets, match and pop on closing brackets.
Complexity: Time O(n) · Space O(n)
Follow-up: Return the minimum insertions needed to make an invalid string valid.
38. Design a Transaction Ledger System Hard
Design an append-only ledger component that records every debit/credit affecting an account balance, guaranteeing the balance can always be reconstructed and audited from the ledger alone.
Ledger.recordEntry(accountId, amount, type, transactionId) // type: DEBIT/CREDIT
Ledger.getBalance(accountId) → decimal
Ledger.getHistory(accountId, fromDate, toDate) → List<Entry>
Approach: Entries are immutable and append-only (never updated or deleted), each tagged with a transactionId for idempotency and traceability. getBalance() is either computed by summing all entries (correct but slow at scale) or served from a maintained running-balance cache that is updated transactionally alongside each new entry and periodically reconciled against the full ledger sum. Key Design Principles: Append-only, immutable entries for auditability, idempotent recording keyed by transactionId, cached balance with periodic reconciliation against the source of truth Follow-up: How do you detect and correct drift if the cached balance ever disagrees with the sum of ledger entries?
39. Design a Card Tokenization Service Medium
Design a service that converts a real card number (PAN) into a non-sensitive token for storage and use in downstream systems, reversible only by the tokenization service itself.
TokenizationService.tokenize(cardNumber) → token
TokenizationService.detokenize(token) → cardNumber // restricted access only
TokenizationService.isValidToken(token) → boolean
Approach: Maintain a secure mapping store (encrypted at rest) of token → encrypted card number, generating tokens as random, format-preserving values with no mathematical relationship to the original PAN (so a leaked token reveals nothing). tokenize() checks for an existing token for that card first (to keep tokens stable per card) before generating a new one. detokenize() is a separately access-controlled, heavily audited operation, most services should only ever need tokenize() and isValidToken(). Key Design Principles: No reversible mathematical relationship between token and PAN (must go through the secure store), strict access control on detokenize(), stable tokens per card to avoid duplicate mappings Follow-up: How would you rotate tokens periodically for security without breaking systems that have already stored the old token?
40. Design a Rate Limiter for Payment Retries Medium
Design a component that limits how many times a failed payment can be automatically retried for the same transaction, using exponential backoff, to avoid hammering a downstream bank/gateway during an outage.
RetryLimiter.shouldRetry(transactionId, attemptNumber) → boolean, nextRetryDelay
Approach: Track attemptNumber and lastAttemptTime per transactionId. shouldRetry() returns false once attemptNumber exceeds a max (e.g. 5), otherwise computes nextRetryDelay = baseDelay * 2^attemptNumber (capped at a maximum), optionally with jitter to avoid synchronised retry storms across many transactions. A background scheduler (or the caller itself) waits for nextRetryDelay before calling shouldRetry() again. Key Design Principles: Exponential backoff with a cap and jitter, per-transaction attempt tracking, hard ceiling on total retries to eventually fail permanently rather than retry forever Follow-up: How do you prevent thousands of failed transactions from all retrying at the exact same moment when a downstream outage resolves (the "thundering herd" problem)?
41. Design a Fraud Rule Engine Hard
Design a component that evaluates an incoming transaction against a configurable set of fraud rules (velocity checks, amount thresholds, geo-mismatch, etc.), producing a risk score, where new rules can be added without changing existing code.
FraudRuleEngine.evaluate(transaction) → { riskScore: int, triggeredRules: List<String> }
// Rules configurable, addable without redeploying core logic
Approach: Each rule implements a common Rule interface (evaluate(transaction) → score contribution + optional reason). The engine holds a list of registered Rule instances (Strategy pattern) and simply iterates and sums their contributions, capping or combining scores via a configurable aggregation strategy. New rules are added by implementing the interface and registering the instance, no changes to the engine itself (Open/Closed Principle). Key Design Principles: Strategy pattern per rule for Open/Closed extensibility, engine only orchestrates and aggregates, does not know rule internals, rules independently testable in isolation Follow-up: How would you support rules that depend on external, slow data (e.g. a device-reputation lookup) without blocking the whole evaluation pipeline?
42. Design a Transaction Reconciliation Service Medium
Design a service that compares Mastercard's internal transaction records against a partner bank's end-of-day settlement file, flagging mismatches (missing, duplicate, or amount-mismatched transactions) for manual review.
ReconciliationService.reconcile(internalRecords, partnerFile) → { matched, missingInternal, missingPartner, amountMismatches }
Approach: Build a HashMap of partner records keyed by transactionId. Iterate internal records: if found in the partner map with a matching amount, mark matched and remove from the map; if found with a different amount, flag as an amount mismatch; if not found, flag as missingInternal (present internally, absent in partner file). Whatever remains unmatched in the partner map after this pass is missingPartner. Key Design Principles: Single-pass HashMap-based matching for O(n) reconciliation instead of nested-loop comparison, clear categorisation of every discrepancy type rather than a single generic "mismatch" bucket Follow-up: The partner file arrives late or corrupted on some days. How does the design handle a reconciliation run needing to be safely re-run without double-flagging already-resolved mismatches?
43. Design a Real-Time Fraud Detection System for Credit Card Transactions Hard
Mastercard's most directly reported system design question. Design a system that scores every credit card transaction for fraud risk in real time, before the transaction is approved, without adding unacceptable latency to the payment flow.
Functional: scoreTransaction(transaction) → riskScore, decision (APPROVE/REVIEW/DECLINE)
Non-functional: <50ms p99 scoring latency, tens of thousands of transactions/second at peak, model updates without downtime
Approach: A low-latency scoring service sits in the critical path of the payment flow, pulling pre-aggregated features (recent transaction velocity, device fingerprint reputation, geo-consistency) from a fast key-value store (Redis) rather than computing them on the fly from raw history. The actual risk model (rule-based + ML) runs as an in-process or co-located inference call to stay within latency budget. A separate, asynchronous pipeline (Kafka + stream processing) continuously updates the pre-aggregated features and retrains/redeploys the model without touching the synchronous request path. Key Design Principles: Strict separation of synchronous scoring (must be fast) from asynchronous feature computation and model training (can be slower), pre-aggregated features in a fast store to avoid expensive real-time joins, hot model swapping for zero-downtime updates Follow-up: How do you handle the case where the fast feature store is temporarily unavailable, fail open (approve) or fail closed (decline/review), and what does that tradeoff mean for the business?
44. Design Batch Transaction Processing at Scale Hard
Design the nightly batch pipeline that processes millions of settled transactions for reporting, reconciliation, and downstream billing, ensuring correctness even if the batch job fails partway through and needs to resume.
Functional: runNightlyBatch(date) → processes all transactions for that date exactly once
Non-functional: millions of transactions per run, must be resumable/idempotent on partial failure, complete within a fixed nightly window
Approach: Partition the day's transactions into independent, checkpointable chunks (e.g. by transaction ID range or by hour). Process chunks in parallel across worker nodes, recording each completed chunk's status in a job-tracking table. On restart after a failure, the orchestrator skips already-completed chunks and only reprocesses the failed/incomplete ones, chunk processing itself is idempotent (safe to redo) since it writes results keyed by transactionId rather than appending blindly. Key Design Principles: Chunked, checkpointable processing for resumability, idempotent writes (keyed by transactionId) so a redone chunk does not double-count, parallel workers to fit within the nightly window Follow-up: How do you size the chunk count to balance parallelism against the overhead of tracking and coordinating many small chunks?
45. Design a Payment Gateway (Monolith-to-Microservices Migration) Hard
Reported as a common Mastercard design prompt. You are given an existing monolithic payment gateway handling authorization, fraud checks, and settlement in one codebase and database. Design an approach to migrate it into microservices without downtime or data loss.
Constraints: zero-downtime migration, no data loss, existing traffic must keep working throughout the migration
Target: separate Authorization, Fraud, and Settlement services with their own datastores
Approach: Strangler Fig pattern: introduce a routing layer in front of the monolith. Extract one bounded context at a time (e.g. Fraud first, since it is largely read-heavy and self-contained), standing up the new service alongside the monolith and routing an increasing percentage of fraud-check traffic to it while the monolith continues handling the rest, validating outputs match before full cutover. Use the Database-per-Service pattern going forward, with a temporary dual-write (or CDC-based sync) during the transition window to keep both the old and new datastores consistent until the monolith's corresponding code path is fully retired. Key Design Principles: Strangler Fig pattern for incremental, low-risk extraction, CDC or dual-write for data consistency during the transition, one bounded context at a time rather than a big-bang rewrite Follow-up: How do you handle a transaction that spans two services mid-migration (e.g. Authorization already extracted, Settlement still in the monolith) without breaking transactional consistency?
46. Find the Duplicate Number Medium
Given an array of n+1 integers where each is between 1 and n, find the one duplicate without modifying the array, using O(1) extra space.
Input: nums = [1,3,4,2,2]
Output: 2
Approach: Treat the array as a linked list (index i points to nums[i]). The duplicate creates a cycle; use Floyd's cycle detection to find its entry point.
Complexity: Time O(n) · Space O(1)
Follow-up: What if there could be multiple duplicates?
47. Kth Smallest Element in a BST Medium
Given the root of a BST and k, return the kth smallest value.
Input: root = [3,1,4,null,2], k = 1
Output: 1
Approach: Inorder traversal visits BST nodes in ascending order; stop at the kth visited node.
Complexity: Time O(h + k) · Space O(h)
Follow-up: Handle frequent insert/delete with repeated kth-smallest queries.
48. Maximum Product Subarray Medium
Given an integer array, find a contiguous subarray with the largest product.
Input: nums = [2,3,-2,4]
Output: 6
Approach: Track both max and min product ending at the current index (a negative can flip a very negative product to the new max).
Complexity: Time O(n) · Space O(1)
Follow-up: Return the actual subarray, not just the product.
49. Rotting Oranges Medium
Given a grid with fresh and rotten oranges, return the minimum minutes until no fresh orange remains, or -1 if impossible.
Input: grid = [[2,1,1],[1,1,0],[0,1,1]]
Output: 4
Approach: Multi-source BFS from all initially rotten oranges simultaneously, processing level by level (minute by minute).
Complexity: Time O(rows * cols) · Space O(rows * cols)
Follow-up: What if rotting happens in all 8 directions instead of 4?
50. Daily Temperatures Medium
Given daily temperatures, return an array where answer[i] is the number of days until a warmer temperature, or 0 if none exists.
Input: temperatures = [73,74,75,71,69,72,76,73]
Output: [1,1,4,2,1,1,0,0]
Approach: Monotonic decreasing stack of indices, popping and recording the wait whenever a warmer day is found.
Complexity: Time O(n) · Space O(n)
Follow-up: Solve the general "next greater element" problem this generalises from.
Preparation Tips
Mastercard's DSA rounds are more forgiving than pure product companies, clean, correct, well-explained solutions to arrays/strings/linked-list problems consistently outperform clever but hard-to-follow optimisations. SQL matters here more than at most product companies given the transaction-heavy domain, be comfortable with joins and window functions, not just SELECT/WHERE basics. For System Design, always answer through a payments lens: fraud detection, batch reconciliation, and safe microservices migration are the three prompts reported most often, know the Strangler Fig pattern and the sync-scoring-vs-async-features split cold.
Join Telegram group to get the latest Mastercard OA questions and connect with candidates currently in the Mastercard interview process.