As a job seeker who has personally taken the Stripe HackerRank OA, I know well the weight of this OA in Stripe’s recruitment process. In the following content, I will share the actual interview questions I encountered myself, and also some high-frequency questions and doubts compiled from numerous real interview experiences of other job seekers.
I also want to recommend a useful tool. I came across Linkjob’s interview assistant, which can provide help during live interviews, but I was a bit worried that the interviewer might notice or that the system could detect it. So, I tried it out with a friend. We found that the answers generated by Linkjob are only visible to the interviewee even when screen sharing, and the response speed is impressively fast. I feel this tool is incredibly useful for online technical interviews.
The following are actual OA questions I encountered myself, along with interview questions mentioned in the experiences I compiled.
Problem Description
Payment card numbers consist of 8-19 digits, with the first 6 digits referred to as the Bank Identification Number (BIN).
For a given BIN, all 16-digit card numbers starting with that BIN are considered to be in the BIN range. For example, the BIN 424242 corresponds to card numbers from 4242420000000000 (inclusive) through 4242429999999999 (inclusive).
Stripe’s card metadata API may return partial coverage of this BIN range, by providing a list of intervals mapping to card brands (e.g., VISA, MASTERCARD). However, these intervals may have gaps (at the beginning, middle, or end of the BIN range), which can be exploited by fraudsters to probe for valid cards.
Your task is to fill in missing intervals so that the returned intervals fully cover the entire BIN range, with no gaps, and return them in sorted order.
Input Format
1. Line 1: A 6-digit BIN.
2. Line 2: A positive integer n, the number of intervals.
3. Next n lines: Each line represents one interval in the format:
start,end,brand
where:
- start and end are 10-digit numbers representing the offset within the BIN range (inclusive).
- brand is an alphanumeric string representing the card brand.
Output Format
Return a list of sorted, gap-free intervals, each covering a contiguous portion of the BIN range, formatted as:
start,end,brand
Where start and end are now full 16-digit card numbers (BIN + 10-digit offset). The output intervals must be sorted by start.
Example
Input
777777
2
1000000000,3999999999,VISA
4000000000,5999999999,MASTERCARD
Output
7777770000000000,7777773999999999,VISA
7777774000000000,7777775999999999,MASTERCARD
Notes
If the input intervals already cover the full BIN range, just return them sorted.
If there are gaps, fill them with intervals extending from previous/next coverage so that no range is uncovered.
Be careful with inclusive endpoints — ensure full coverage from BIN0000000000 to BIN9999999999.
I highly recommend you give Linkjob a try. I tested it once and instantly loved it. I think the most useful feature during coding interviews is that it allows you to take screenshots, or you can also upload files. This way, the AI can see the exact question you want it to answer.
They’re even offering a free test key right now, so you might as well take advantage of it.
Background
Stripe processes billions of dollars worth of transactions every day. Our job is to protect customers and legitimate merchants by detecting and blocking fraudulent transactions. We will build a simplified fraud detection model that marks merchants as fraudulent if too many of their transactions are suspicious. The problem is split into three parts.
Part 1: Count-Based Fraud Detection
Each merchant has a Merchant Consumer Code (MCC) that represents their industry (e.g., retail, airline). Each MCC has an associated fraud threshold (integer > 1) that indicates the maximum allowed number of fraudulent transactions before the merchant is marked as fraudulent.
We are given
A comma-separated list of non-fraudulent codes (e.g., "approved,invalid_pin,expired_card").
A comma-separated list of fraudulent codes (e.g., "do_not_honor,stolen_card,lost_card").
A table of MCCs with their fraud thresholds: MCC,threshold (one per line).
A table of merchants with their MCCs: account_id,MCC.
The minimum number of total transactions we must observe before evaluating a merchant (integer ≥ 0).
A table of charges: CHARGE,charge_id,account_id,amount,code
Output
Return a lexicographically sorted, comma-separated list of fraudulent merchants (by account_id).
Part 2: Percentage-Based Fraud Detection
Count-based thresholds can unfairly mark high-volume merchants as fraudulent. Instead, use a percentage threshold:
Each MCC now has a fraction between 0 and 1 indicating the maximum allowed fraction of fraudulent transactions.
If a merchant’s fraud percentage ≥ threshold, mark them as fraudulent.
Merchants stay fraudulent even if their fraud percentage later decreases.
Only evaluate merchants after seeing at least the minimum number of total transactions.
Inputs remain the same as Part 1, except the MCC table now contains fractions.
Part 3: Dispute Resolution
Sometimes transactions are incorrectly marked as fraudulent. We now support disputes which overturn the fraudulent status of a specific transaction.
Input now may include lines like: DISPUTE,charge_id
When a dispute is present, that transaction is treated as not fraudulent for all calculations. If a merchant was marked fraudulent solely due to disputed transactions, they may return to non-fraudulent status until they cross the threshold again with new transactions.
Problem Description
We own a store that records, hour by hour, whether there were customers shopping. Each hour is marked with a single letter:
'Y' if there were customers during that hour
'N' if the store was empty during that hour
Example log for 4 hours:
hour: | 1 | 2 | 3 | 4 |
log: | Y | Y | N | Y |
Here, there were customers for hours 1, 2, and 4, and no customers in hour 3.
We want to analyze when we should have closed the store to minimize wasted hours. The closing time is expressed as an integer from 0 to n:
0 → never open at all
n → open the entire day
Closing time is measured in hours from the start of the day:
hour: | 1 | 2 | 3 | 4 |
closing_time: 0 1 2 3 4
Penalty Definition
For a given closing_time, define penalty as:
+1 for every hour we were open with no customers (unnecessary open time)
+1 for every hour we were closed with customers present (lost opportunity)
Part 1: Compute Penalty
Write a function:
def compute_penalty(log: str, closing_time: int) -> int:
...
where:
log is a space-separated string of 'Y' / 'N'
closing_time is an integer between 0 and len(log)
Return the total penalty.
Part 2: Find Best Closing Time
Write a function:
def find_best_closing_time(log: str) -> int:
...
that returns the closing time that yields the minimum penalty (using compute_penalty). If multiple closing times yield the same minimum penalty, return the smallest closing time.
Part 3: Aggregate Logs
Sometimes, employees record multiple days’ logs in one file. Valid logs are sequences that start with BEGIN, followed by zero or more 'Y' / 'N', and end with END. There can be extra garbage text or unfinished logs, which must be ignored.
Rules:
Valid logs cannot be nested (no BEGIN ... BEGIN ... END inside).
Valid logs can span multiple lines.
There may be multiple valid logs per line.
Write a function:
def get_best_closing_times(aggregate_log: str) -> list[int]:
...
that:
Parses the aggregate log string
Extracts all valid logs in order
Returns an array of best closing times (using Part 2 for each valid log)
Linkjob isn’t just for technical questions. In theory, it can handle all kinds of interview questions. For example, in other stages of my Stripe interview where I had to respond in a conversational format, it could listen to the interviewer’s voice and generate answers based on my resume and the job description. And the best part is that I didn’t need to operate it manually, because it could detect when the interviewer finished asking a question and then provide me with an answer within two seconds.
Problem Description
You are asked to implement a notification system for subscription plans. Each user subscribes to a plan with a start date and a duration (in days). You must schedule and print emails at the correct dates based on the rules provided.
Part 1: Basic Email Scheduling
Input
send_schedule – A mapping from relative day offsets to email message types:
"start" → send on the subscription start day
Negative integers (e.g., -15) → send before subscription end date
"end" → send on the subscription end date
user_accounts – A list of user dictionaries with:
name: string – user name
plan: string – subscription plan
account_date: int – day subscription started
duration: int – duration of subscription in days
Output
Print one line for each email event in ascending order of day. Each line format:
<day>: [<Email Type>] Subscription for <name> (<plan>)
Part 2: Handling Plan Changes
Now you are given an additional input: a list of plan change events. When a user changes plan, you must:
Print a [Changed] message on the change date
Recalculate the remaining duration relative to the change date
Schedule future notifications (upcoming expiry, expired) based on the new plan and updated timeline
Input
users – same as Part 1
changes – list of dictionaries:
name: user name
new_plan: new plan name
change_date: day the plan changed
Output
Include [Changed] events in chronological order, and base upcoming-expiry / expired events on the updated plan.
Part 3: Bonus: Renewals
In addition to plan changes, you now have renewal events in the change list. Each renewal extends the subscription duration by the given number of days. You must:
Print [Renewed] on the renewal date
Reschedule future emails based on the new end date
Input
changes may now have two kinds of events:
Plan change: {name, new_plan, change_date}
Renewal: {name, extension, change_date}
Output
Include [Renewed] events and re-schedule upcoming-expiration and expired events accordingly.
Background
Stripe processes billions of dollars through various payment methods. To ensure payment security, card numbers must be validated before processing.
This system requires:
Network detection (VISA, MASTERCARD, AMEX).
Luhn algorithm validation.
Handling of redacted and corrupted card inputs.
Card Networks
VISA: 16 digits, starts with 4.
MASTERCARD: 16 digits, starts with 51–55.
AMEX: 15 digits, starts with 34 or 37.
Luhn Algorithm
From the rightmost digit (excluding the check digit), double every second digit.
If a doubled digit > 9, subtract 9.
Sum all digits.
If sum % 10 == 0, the card is valid.
Example
Card: 4532015112830366
Step 1: Double every 2nd from right → 8 5 6 2 0 1 1 1 2 2 7 3 0 3 3 6
Step 2: Sum = 50
Step 3: 50 % 10 = 0 → Valid
Part 1: Basic Visa Validation (Test Cases 1–5)
Input: 16-digit number starting with 4.
Output:
"VISA" if checksum passes.
"INVALID_CHECKSUM" if checksum fails.
Examples
Input: 4532015112830366 → Output: VISA
Input: 4242424242424243 → Output: INVALID_CHECKSUM
Part 2: Multi-Network Validation (Test Cases 6–10)
Input: 15- or 16-digit card number.
Output:
Network name (VISA / MASTERCARD / AMEX) if valid.
"INVALID_CHECKSUM" if checksum fails.
"UNKNOWN_NETWORK" if length or prefix does not match any known network.
Examples
Input: 5482334509943 → Output: UNKNOWN_NETWORK (13 digits)
Input: 4425233430109994 → Output: VISA
Input: 562523343010901 → Output: UNKNOWN_NETWORK (prefix 56)
Part 3: Redacted Cards (Test Cases 11–15)
Input: A card number containing * (1–5 digits redacted).
Output: Count of valid cards per network, sorted alphabetically by network.
Examples
Input: 4242424242424*42 → Output: VISA,1
Input: 3*8282246310005 → Output: AMEX,2
Input: **2424242424242 → Output:
MASTERCARD,5
VISA,10
Part 4: Corrupted Cards (Test Cases 16–20)
Input: A card ending with ?, meaning exactly one error occurred:
One digit may have been changed.
Two adjacent digits may have been swapped.
Output: All possible valid original cards, in ascending numeric order.
Format:
card_number,NETWORK
Example
Input: 4344555566660004?
Output (partial):
4342555566660004,VISA
4344555566660004,VISA
4344555566660014,VISA
...
Implementation Notes
Output strings must match exactly.
Sort results numerically for Part 4.
Sort results alphabetically by network for Part 3.
Handle edge cases: wrong lengths, invalid prefixes.
Optimize for large search spaces.
Stripe chooses the HackerRank platform for online assessments, leveraging its rich question bank and powerful evaluation functions to efficiently screen technical talents that meet the company's needs. The HackerRank platform is known for offering diverse programming challenges, covering algorithms, data structures, programming language features, and other fields, ensuring that candidates' technical levels are fully tested.
Programming Skills
Candidates are required to be proficient in at least one mainstream programming language, such as Python, Java, or C++. Questions will involve complex algorithm implementation, data structure operations like traversal and processing of linked lists, trees, and graphs, as well as the application of advanced algorithms such as dynamic programming and greedy algorithms.
Problem-Solving Ability
Candidates are presented with practical scenario problems, such as financial transaction processing and payment system optimization, to assess their ability to analyze problems, design solutions, and implement them in code. This requires candidates to have the ability to break down complex problems into solvable sub-problems and the skills to use programming knowledge to build effective solutions.
Time and Space Complexity Analysis
When solving problems, candidates need to consider the time and space complexity of algorithms. Optimizing algorithms to improve efficiency and avoid performance bottlenecks caused by inefficient algorithms with large-scale data is an important dimension of the assessment.
Algorithm Implementation Questions
Such as implementing an efficient sorting algorithm, search algorithm (binary search, depth-first search, breadth-first search, etc.), or solving classic algorithm problems like the knapsack problem and the longest common subsequence problem.
Data Structure Operation Questions
Including operations such as creation, insertion, deletion, and search for data structures like arrays, linked lists, stacks, queues, trees, and graphs.
System Design Questions
They will involve some system design problems, such as designing a small payment system module, considering the system's architecture, inter-module communication, data storage, and other aspects.
Systematic Learning and Problem Solving
Review data structures and algorithms comprehensively. Solve problems on platforms like HackerRank and LeetCode to familiarize yourself with various question types and problem-solving approaches. Focus on summarization and induction to form your own problem-solving templates and thinking patterns.
Understand Business Scenarios
Learn about Stripe's business areas, such as payment systems and financial transaction processing. Combining technical knowledge with actual business scenarios helps you better understand question requirements and design solutions that are more in line with practical needs.
Optimize Code
During practice, not only should you implement the functionality, but also pay attention to optimizing the time and space complexity of the code, and improve the readability and maintainability of the code. This is a very important ability in both actual interviews and work.
For me, the OA was of medium difficulty. However, Stripe’s HackerRank OA questions are not like regular LeetCode problems, since the descriptions are quite lengthy and take a lot of time to understand.
The OA usually lasts 60 minutes and includes several questions.