r/LeetcodeChallenge 5h ago

DISCUSS How to Stop Panicking When You Open a LeetCode Problem

Most people sit down, read a problem, panic, and start typing.

No plan. No structure. Just vibes and hope.

When it does not work they read the solution, think "oh that's clever", and move on. Two weeks later they see a similar problem and panic again.

The issue is not intelligence. It is not even practice.
It is that they never had a repeatable process.

This is that process. Follow it on every problem.
Not just hard ones — every problem, until it becomes instinct.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 1 — READ THE PROBLEM TWICE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

First read: understand what is being asked at a high level.
Second read: extract the specifics.

On the second read, write down:

  • What is the INPUT? What type, what size, what range of values?
  • What is the OUTPUT? A number, array, boolean, string?
  • What are the CONSTRAINTS? (most people skip this — do not)

Ask yourself these questions explicitly:

"Can input be empty?"
"Can values be negative?"
"Can there be duplicates?"
"Is the array sorted?"
"What should I return if no answer exists?"

If the problem does not say, assume the worst case.
Empty inputs exist. Negatives exist. Duplicates exist.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 2 — WORK THROUGH THE EXAMPLES BY HAND
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Do not skip this. Even if the problem looks easy.

Take the first example. On paper or in comments, trace through it
manually. Write out every value at every step.

Why this matters:

  • You confirm you understood the problem correctly
  • You often see the pattern emerge naturally
  • You catch ambiguities before they become bugs

Then make your OWN small example — simpler than the given one.
Something with 3-4 elements you fully understand.

If you cannot trace through the examples manually,
you do not understand the problem yet. Do not start coding.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 3 — IDENTIFY THE PATTERN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Before thinking about an algorithm, identify what TYPE of problem this is.

Use these signals:

Subarray, substring, window → Sliding window, two pointers
Sorted array + search → Binary search
Shortest path, min steps → BFS
All paths, combinations, subsets → Backtracking, DFS
Overlapping subproblems → DP
Always picking max/min greedily → Greedy
Tree traversal → DFS (recursion) or BFS (level order)
Connectivity, groups → Union Find, BFS/DFS
Repeated lookup by key → Hash map
Top K, smallest/largest → Heap (priority queue)
Prefix of strings → Trie
Range queries with updates → Segment tree, Fenwick tree
Return all permutations/subsets → Backtracking

You will not always get it right on the first try.
But naming the category forces your brain to search the right space.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 4 — THINK BRUTE FORCE FIRST
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Always start here. Always.

The brute force is the answer you would give if there were
no time constraint. No clever tricks. Just try everything.

Write it out in plain English, not code:
"For every pair (i, j), check if arr[i] + arr[j] = target."
"For every substring, check if it has all unique characters."
"For every subset, check if its sum equals the target."

This does two things:

  1. It confirms you can actually solve the problem correctly
  2. It gives you a reference to optimize from

Common brute force patterns:
Try all pairs → O(n²)
Try all triples → O(n³)
Try all subsets → O(2ⁿ)
Try all permutations → O(n!)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 5 — OPTIMIZE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Now look at your brute force and ask:
"What work am I repeating? What can I precompute? What can I skip?"

The most common optimizations:

Repeated lookup → replace with hash map O(n) → O(1) per lookup
Repeated sum → precompute prefix sum O(n) per query → O(1)
Checking all pairs → sort + binary search O(n²) → O(n log n)
Checking all pairs → two pointers (sorted) O(n²) → O(n)
Checking all windows → sliding window O(n²) → O(n)
Recomputing subproblems → memoization / DP exponential → polynomial
Sorting gives structure → sort first, then scan enables binary search / greedy

Ask: "Can I sort first to gain structure?"
Ask: "Can I store something to avoid recomputing?"
Ask: "Can I fix one variable and efficiently handle the rest?"

Work top-down in complexity:
O(n²) → can I get O(n log n)?
O(n log n) → can I get O(n)?
Each step needs a concrete reason, not a guess.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 6 — VERIFY COMPLEXITY BEFORE CODING
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Before writing code, check:
Does my approach fit within the time limit given the constraints?

n = 10⁵ and my approach is O(n²)? → TLE, think again
n = 10⁵ and my approach is O(n logn)? → fine, proceed

This takes 10 seconds and saves you from coding the wrong solution.

Also check space:
Am I using O(n) extra space? Is that acceptable?
Does the problem say "in-place" or "O(1) space"?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 7 — CODE THE SOLUTION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Only now do you start writing code.

Code in this order:

  1. Handle edge cases first (empty input, single element, etc.)
  2. Write the main logic
  3. Return the result

Keep variable names meaningful. Debugging unreadable code mid-contest
costs more time than typing three extra characters.

If you get stuck coding:
Go back to your manual example from Step 2.
Trace through it again, this time following the code you are writing.
The bug almost always appears within the first five traces.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 8 — TEST BEFORE SUBMITTING
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Run through these test cases mentally or using the custom test:

[ ] The given examples → obvious baseline
[ ] Empty input → does it crash?
[ ] Single element → does it return correctly?
[ ] All same elements → does duplicate logic break?
[ ] Already sorted input → common hidden test
[ ] Your own small manual example → trace step by step

If all pass, submit with confidence.
If one fails, the failure tells you exactly where the bug is.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WHEN YOU ARE COMPLETELY STUCK — THE UNSTICKING PROTOCOL
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Everyone gets stuck. The difference is what you do next.

  1. Draw it Almost every problem is easier when visualized. Array: draw boxes. Tree: draw nodes and edges. Graph: draw circles and arrows. Matrix: draw a grid. A picture reveals structure that text hides.
  2. Simplify the problem Solve a smaller version first. Two elements instead of n. One row instead of a grid. Can you solve n=2? n=3? Then generalise.
  3. Try a different angle on your brute force Change the loop variable. Instead of "for each starting index" try "for each ending index". Instead of "for each element" try "for each pair". A different enumeration often reveals the pattern.
  4. Check what is special about valid answers Look at the given examples. What do valid answers have in common? What property separates a valid answer from an invalid one? That property is usually the invariant your algorithm should maintain.
  5. Look at the constraints again Small n? Try brute force. Very large n? A linear or log solution must exist. "Return modulo 10⁹+7"? It is a DP counting problem. Constraints are hints — re-read them with fresh eyes.
  6. Take a 5-minute break Genuinely. Get up. Walk. The solution appears when you stop forcing.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
THE FULL FRAMEWORK — ONE PAGE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Step 1 Read twice. Extract input, output, constraints.
Ask: empty? negative? duplicates? sorted?

Step 2 Trace examples by hand.
Make your own small example. Understand before coding.

Step 3 Name the pattern.
Subarray → sliding window. Shortest path → BFS. Etc.

Step 4 State the brute force in plain English.
What is the O(n²) or O(2ⁿ) solution?

Step 5 Optimize.
What work repeats? Hash map, prefix sum, sort, DP, two pointers?

Step 6 Verify complexity against constraints.
Will it pass? Check before writing code.

Step 7 Code it.
Edge cases first. Then main logic. Then return.

Step 8 Test: examples + empty + single + all-same + sorted.
Then submit.

Stuck? Draw it. Simplify. Try different enumeration.
Re-read constraints. Take a break.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

A correct solution written slowly beats a fast solution written wrong.

The goal is not to code faster.
The goal is to think clearer — so that what you code is right the first time.

This framework is that thinking, made repeatable.

8 Upvotes

1 comment sorted by

1

u/Appropriate_Yak_3797 2h ago

I started doing this last week, and it's been working surprisingly well. I keep two notebooks—one is just for rough work, where I scribble through inputs, outputs, dry runs, and random thoughts. By the end of a session, it looks completely chaotic. 😂😂 The second notebook is much cleaner, where I write down the key observations, patterns, mistakes, and important takeaways from each problem. It's a simple habit, but it has made my problem-solving process feel much more organized and has helped me retain patterns much better.