Discover how to solve Data Structures and Algorithms problems like a strong software engineer—from understanding the problem to optimizing your solution, writing clean code, and analyzing Big-O complexity. Learn through a real-world e-commerce example from Varastra.
Why Your First Answer Fails Coding Interviews (And the 6-Step Fix)
A correct answer is not enough. You must also know what it costs. A simple six-step method teaches this, and Varastra shows how it works.
The problem at Varastra
Varastra is an online store for Indian ethnic wear. It sells sarees, kurtas and lehengas. Tara is a new intern there.
In her first week, Sam, a senior engineer, gives her a task. The payment partner sends a file of order IDs. Sometimes one ID comes twice. Then a parcel gets packed twice. Tara must write code that tells if any ID repeats.
She writes two loops in under a minute. She runs them on five IDs. It works.
Then Sam asks one question: "What does it cost?" Tara has no answer. Her code is correct. But she cannot say if it is good enough for the biggest sale night of the year, when the file may hold 200,000 orders.
The diagram at a glance
Think of the method as a staircase. The diagram shows six steps in two rows of three. Read the top row first, from left to right.
- Ask. Clarify the problem. Ask about the limits.
- Try small. Solve one tiny example by hand.
- Brute force, said out loud. State the simple answer and its cost.
- Improve. Find the pattern that cuts the cost.
- Code. Write clean code in a plain editor.
- Test. Dry-run it. Find your own bugs. State the Big-O.
The first three boxes are shaded. These are the steps you finish before you write any code. Use all six steps on every problem.
Step 1: Ask
Tara typed first and asked nothing. That was her first mistake. Before any code, she should ask four questions.
- What is an order ID? A number, or text like "VA10432"?
- How many IDs can the file hold? Hundreds, or hundreds of thousands?
- What should the code return? Yes or no, or the repeated ID?
- Can the file be empty? Can it hold just one ID?
The size question matters most. The cost of any answer depends on it. We call the number of items n. Here, n is the number of order IDs in the file.
Sam answers: "IDs are text. The file can reach about 200,000. Return yes or no." Now Tara knows n can be 200,000.
Step 2: Try small
Now Tara takes six IDs and works by hand.
VA101, VA102, VA103, VA104, VA105, VA102
To be sure about repeats, she compares every ID with the ones after it. VA101 is compared with five IDs. VA102 with four. Then three, two and one.
That is 5 + 4 + 3 + 2 + 1 = 15 comparisons for only 6 IDs. With 7 IDs it is 21.
Pause and predict
Before you read on: a file holds 10 order IDs. How many comparisons does the pair method make in the worst case?
Answer: 45. The formula is n × (n − 1) ÷ 2, so 10 × 9 ÷ 2 = 45.
You can let the computer count for you. This small function runs the same two loops and counts each comparison.
def count_pair_comparisons(n):
count = 0
for i in range(n):
for j in range(i + 1, n):
count += 1
return count
print(count_pair_comparisons(6)) # 15
print(count_pair_comparisons(7)) # 21
The count grows faster than the list. One new ID adds a whole new row of comparisons. For n IDs, the formula is n × (n − 1) ÷ 2. Check it with 6 IDs: 6 × 5 ÷ 2 = 15. It matches the hand count.
Step 3: Brute force, said out loud
Brute force means trying every possibility until one fits. It is simple and it is correct. The skill is to say it out loud, with its cost. Here is what Tara should tell Sam.
"My first idea is to compare every ID with every ID after it. If any two match, I return yes. Otherwise I return no. For n IDs, that is about n × n ÷ 2 comparisons. It is correct. It will be slow for large n. Let me see how slow."
Try it
In the counting code above, change the last two calls to count_pair_comparisons(100) and count_pair_comparisons(1000). What do you expect? Remember that one new ID adds a whole new row.
You get 4,950 and 499,500. Ten times more IDs gave about 100 times more comparisons. That is the O(n²) shape.
Here is that brute force idea as code.
def has_duplicate_pairs(order_ids):
n = len(order_ids)
for i in range(n):
for j in range(i + 1, n):
if order_ids[i] == order_ids[j]:
return True
return False
The outer loop picks one ID. The inner loop compares it with every ID after it. The inner loop starts at i + 1, so no pair is checked twice.
She gave a working answer, named its cost, and said it might not be enough. That took four sentences. This keeps the door open in an interview.
Sam always writes a cost line on a sticky note before any code. Now Tara fills in that note. The worst case is a file with no repeat, because then the code checks every pair.
| IDs in the file (n) | Comparisons | Time |
|---|---|---|
| 6 | 15 | too small to notice |
| 2,000 (a normal day, in the story) | 1,999,000 | about 0.06 seconds (estimated) |
| 10,000 | 49,995,000 | 1.6 seconds (measured) |
| 200,000 (biggest sale night, in the story) | 19,999,900,000 | about 11 minutes (estimated) |
Only the 10,000 row was timed. The other times come from that speed, so they are estimates. All Varastra numbers in the story are made up.
Now read the last row as a business problem. The packing team waits for the clean file. If the check takes 11 minutes, the warehouse sits idle. Orders miss the courier pickup. Customers get late parcels.
So the cost line on the sticky note reads: about n × n ÷ 2 comparisons. For 200,000 orders, too many.
Steps 4 to 6: Improve, code, test
Only now does Tara look for something better. Sam asks, "What work do you repeat?" She sees it. For every new ID, her code searches the whole list again.
The fix is a set. A set is a container that answers one question very fast: "Is this item already inside?" Think of a building gate register. The guard checks a name in one look. He does not read the list from the top.
def has_duplicate_set(order_ids):
seen = set()
for order_id in order_ids:
if order_id in seen:
return True
seen.add(order_id)
return False
This is step 5, Code. The code makes one pass over the list. Each ID is checked once.
Step 6 is Test. Tara tries the cases she listed in step 1: an empty list, one ID, two equal IDs, a repeat at the very end, and no repeat at all. She also checks both methods against each other on random lists. If a slow method and a fast one agree, bugs are rare.
import random
def test_duplicates():
cases = [
([], False),
(["VA1"], False),
(["VA1", "VA1"], True),
(["VA1", "VA2", "VA3", "VA1"], True),
(["VA1", "VA2", "VA3"], False),
]
for ids, expected in cases:
assert has_duplicate_pairs(ids) == expected
assert has_duplicate_set(ids) == expected
# Compare the slow method and the fast method on random lists
for _ in range(500):
size = random.randint(0, 20)
ids = [f"VA{random.randint(1, 30)}" for _ in range(size)]
assert has_duplicate_pairs(ids) == has_duplicate_set(ids)
test_duplicates()
Then she states the cost out loud. At 10,000 IDs, the pair method took 1.6 seconds. The set took 0.0004 seconds. Both are correct. Only one is ready for sale night.
Sam writes the new line on the sticky note: Cost: about n steps, plus space for n IDs. The set trades memory for time.
Why the six steps matter
The method guards you against two traps.
- Brute Instinct. You type the first idea that works and never ask what it costs.
- Silent Stall. You freeze or code in silence, so nobody sees how you think.
In an interview, an interviewer may follow your first answer with "Can you do better?" If you never counted the cost, you cannot say what better means. The six steps give you words for every moment, even when you are stuck.
Tara did not pick the cleverest tool. She asked about the size, tried a small case, and said the cost out loud. The set came after that.
Takeaway: Say your first answer out loud. Say what it costs. Then improve it.
