DSA 16 Patterns

These 16 DSA Patterns Did What 3000 LeetCode Problems Couldn’t

When I started with DSA, I did what everyone else does. I opened LeetCode. Picked Easy. Clicked “Run”. Then “Submit”. Got a green tick. I…

Himanshu Singour

Himanshu SingourFollow

androidstudio·June 19, 2025 (Updated: June 19, 2025)·Free: Yes

When I started with DSA, I did what everyone else does. I opened LeetCode. Picked Easy. Clicked “Run”. Then “Submit”. Got a green tick. I felt smart.

But in interviews? I choked. Repeatedly.

I had solved over 3000 problems across platforms from LeetCode to Codeforces. Still, the moment someone asked me a real-world DSA question, my mind went blank.

I wasn’t stupid. I just didn’t have structure. I was solving 3000 problems like they were 3000 random puzzles. What I needed was to see the patternbehind the problem.

And once I discovered that everything changed.

16 DSA patterns that finally made me stop memorizing and start solving.

1. Sliding Window, When You Don’t Want to Repeat the Same Work

What Happened:

I got this question

“Find the maximum sum of any subarray of size k.”

I wrote two loops:

  • First loop to pick the start point
  • Second loop to add the next kelements

It worked. But when the array got bigger, my code became slow. It was checking too much again and again.

What I Realized:

Why am I calculating the same thing again?

If I already know the sum of a window, and I’m just moving 1 step forward I can:

  • Subtract the element going out
  • Add the new element coming in

That’s called Sliding Window.

When to Use:

  • When you’re working with arrays or strings
  • When the question asks about a range or subarray
  • And the size of that range is fixed (or sometimes flexible)

How It Works:

Let’s say we have:

CopyArray: [1, 2, 3, 4, 5], Window size k = 3
  • First window: 1 + 2 + 3 = 6
  • Next window: Instead of adding 2 + 3 + 4 again, we do: 6–1 (remove first) + 4 (add next) = 9
  • Keep doing this till end

Now you’re only doing work once, and just adjusting.

Why It’s Amazing:

Because you’re using your previous answer smartly. No more doing the same math again and again.

It saves a lot of time goes from O(n*k) to just O(n).

2. Two Pointers, When You Want to Check from Both Sides

What Happened:

I had to check if a word is a palindrome (same forward and backward).

I used to reverse the string and compare. But that’s extra work and takes more memory.

What I Realized:

Why not just check from both sides?

Use one pointer at the beginning, and one at the end and move them toward each other.

When to Use:

  • When you’re working with arrays or strings
  • When you want to compare from both ends
  • Great for palindrome, pair-sum, reversing, etc.

How It Works:

Example: "madam"

  • Compare 1st and last: m == m
  • Then 2nd and 2nd last: a == a
  • Then middle: done

Another use:

CopyArray: [1, 2, 3, 4, 6], Target = 6
  • Start = 1, End = 6 → 1+6 = 7 → too big → move end left
  • Start = 1, End = 4 → 1+4 = 5 → too small → move start right
  • Start = 2, End = 4 → 2+4 = 6 Found!

Why It’s Powerful:

Because you’re not checking every possible pair you’re moving smartly based on conditions.

No need for two loops. Just two fingers sliding inward.

3. Fast and Slow Pointers, When You Want to Catch a Cycle

What Happened:

I was asked:

“How do you find if a linked list has a cycle?”

I used a Set to store visited nodes. It worked, but it used extra memory.

What I Learned:

There’s a smarter way use two pointers:

  • One moves slowly (1 step)
  • One moves faster (2 steps)

If there is a loop, they will meet. If not, the fast one will reach the end.

When to Use:

  • When checking if something loops or cycles
  • Mostly in linked lists or circular paths
  • Also used in some array problems

How It Works:

Example:

Copy1 -> 2 -> 3 -> 4 -> 2 (back to node 2 = cycle)

Steps:

  • slow = 2, fast = 3
  • slow = 3, fast = 2
  • slow = 4, fast = 4 → same → cycle found

Why It’s Smart:

It uses no extra space And it’s super fast just two pointers running at different speeds.

You catch the cycle like one person chasing another on a circular track. Eventually, they’ll meet.

4. Prefix Sum, When You Keep Getting “Find the Sum from X to Y” Type Questions

My Struggle:

I had this question:

“Find the sum of elements from index 2 to 5.”

I did what most beginners do I used a loop every time to sum from index 2 to 5. It worked… but then I had to do it 100 times. And suddenly my code was slow.

The Realization:

Why am I doing the same sum again and again?

That’s when I found this trick called Prefix Sum.

When to Use:

  • When the problem asks: “Sum from index i to j?”
  • Or: “How many times something happened up to index k?”
  • Best for arrays where you do many range sum queries

How It Works:

You build a new array called prefix[]where:

Copyprefix[i] = sum of all elements from 0 to i

Let’s take a simple array:

Copyarr = [1, 2, 3, 4, 5]

Now build prefix sum:

Copyprefix = [1, 3, 6, 10, 15]

Now, to get sum from index 2 to 4 (which is 3 + 4 + 5 = 12):

Just do:

Copyprefix[4] - prefix[1] = 15 - 3 = 12

Why It’s Helpful:

Because instead of looping every time to calculate a sum you can now answer it in just 1 subtraction.

It changes your code from O(n) to O(1)per query.

And if you get 100 such queries? Your total time goes from 100*n → just 100

5. Binary Search, When You Need to “Search Smart”

My Struggle:

I thought binary search was only for finding a number in a sorted array. So I used it once or twice and ignored it after that.

But later I realized it’s way more powerful than that. You can use binary search to optimizeminimize, or maximize things.

When to Use:

  • When the array is sorted
  • Or when you’re told to “find the minimum/maximum value” that satisfies a condition
  • Or any time you’re dealing with searching in a range

How It Works:

You start with a range: low and high. You keep checking the mid value.

Depending on the condition, you either:

  • Move to the left half (if mid is too big)
  • Or move to the right half (if mid is too small)

Simple Example, Classic Search:

Copyarr = [1, 3, 5, 7, 9], target = 5
  • mid = 5 → found!

Now let’s see a non-obvious example:

Example, Square Root of 10

You want to find the square root of 10 up to 2 decimal places.

Try mid = (1 + 10) / 2 = 5.5 → 5.5 * 5.5 = 30 → too high → move left

Keep narrowing the range. Finally, you’ll reach something like 3.16

This is binary search but on answers, not elements.

Why It’s Powerful:

Because it cuts the search space in half every time.

So even if your range is 1 to 1 billion you’ll find the answer in just ~30 steps.

6. Two Heaps, When You Need a Live Median or Top k Elements

My Struggle:

I got this problem:

“Keep adding numbers and find the median after each add.

I was totally stuck.

How do I keep track of the middle element every time?

I tried sorting the list after every insertion. That was too slow.

The Realization:

Use two heaps:

  • One max heap for the smaller half of numbers
  • One min heap for the bigger half

When to Use:

  • When the input is coming in live / stream
  • And you want to find the median, or top K numbers
  • Used in real-world apps like stock prices, live score tracking

How It Works:

Let’s say you get numbers: 1, 2, 3, 4, 5

Step by step:

  • Add 1 → goes to left heap → median = 1
  • Add 2 → goes to right heap → median = (1+2)/2 = 1.5
  • Add 3 → left: [1,2], right: [3] → balance → median = 2

You keep both heaps balanced, so that median is easy to find:

  • If total count is odd → median is top of bigger heap
  • If even → average of both tops

Why It’s Useful:

Because it gives you the answer in real-time, without sorting again and again.

Also very efficient: insertions take O(log n), median takes O(1)

7. Bit Manipulation, When You Want to Use Math Magic

My Struggle:

I got this question:

“In an array where every number appears twice except one, find the number that appears only once.

I tried using a HashMap to count frequencies. It worked… but wasn’t very efficient.

Then I saw a one-line solution using something called XOR.

I didn’t understand it at first. But once I did, it felt like math + magic.

When to Use:

  • When question talks about even-odd appearances
  • Or if it says “every number appears twice except one”
  • Or if you want to check even/odd, or swap numbers without extra space

How It Works:

The trick here is XOR (^) a bitwise operation.

It follows a few cool rules:

  • a ^ a = 0
  • a ^ 0 = a
  • a ^ b ^ a = b (because a ^ a = 0, and 0 ^ b = b)

So if we XOR all the numbers:

Copyarr = [2, 3, 2]

Do: 2 ^ 3 = 1 1 ^ 2 = 3 → so the answer is 3

Why It’s Cool:

You don’t need extra space or loops. You just scan the array once and get the answer.

Bit manipulation is also used in:

  • Checking if a number is even: num & 1 == 0
  • Dividing/multiplying by 2: num << 1(multiply), num >> 1 (divide)
  • Counting set bits: num & (num - 1)

Pro Tip:

It sounds hard at first, but once you try a few problems, it becomes really fun like doing puzzles with switches.

8. Dynamic Programming (DP), When Your Code Keeps Repeating the Same Work

My Struggle:

I got this classic question:

“You can climb 1 or 2 steps at a time. How many ways to reach the top if there are n steps?”

I used recursion:

Copyways(n) = ways(n-1) + ways(n-2)

It worked… until n = 35 and my code became super slow. Why? Because it was calculating the same thing again and again.

The Realization:

In Dynamic Programming, you don’t recalculate. You store answers (called “memoization”).

When to Use:

  • If the problem breaks into smaller subproblems
  • And the same subproblem is being solved many times
  • Words to look for: “maximum”, “minimum”, “ways to do something”

How It Works:

Let’s take the climbing stairs example again.

For n = 5, you want to know:

Copyways(5) = ways(4) + ways(3)

So you just store results for:

Copyways[1] = 1  
ways[2] = 2  
ways[3] = 3  
...

You build from bottom up:

Copyfor (i = 3 to n):
    dp[i] = dp[i-1] + dp[i-2]

No repetition. Fast. Clean.

Real-Life Examples:

  • Longest Increasing Subsequence
  • Knapsack (bag full of items)
  • Coin change
  • Palindromic substrings
  • Edit distance (word conversions)

Why It’s Powerful:

Because it takes a slow, repeating solution… and makes it fast.

From O(2^n) → to O(n)

Pro tip: Always ask: “Am I solving the same small problem again and again?” if yes, it’s probably DP.

9. Backtracking, When You Have to Try Everything But Not Stupidly

My Struggle:

I got a question:

“Generate all possible combinations of well-formed parentheses.

I tried brute-force made all strings of (and ) and then checked which ones are valid.

That worked, but it created way too many strings.

Then I learned about Backtracking a way to explore all possibilities, but smartly.

When to Use:

  • When you need to find all combinations
  • Or generate valid sequences
  • Or explore paths in a maze, tree, or board

How It Works:

Backtracking is like:

  • Try a choice
  • Go forward
  • If it fails, go back and try a different choice

It’s like solving a maze: You try a path if it hits a wall, you go back and take another.

Example, Parentheses

You want to generate all valid pairs of 2 brackets:

Start with empty string: ""

  • Try adding ( → "("
  • Try adding ( again → "(("
  • Can’t add ( anymore (limit reached), so try ) → "(()"
  • Keep going
  • If invalid, backtrack and change path

Other Famous Examples:

  • N Queens
  • Sudoku Solver
  • Word Search on a grid
  • Subsets / Permutations / Combinations

Why It’s Beautiful:

Because you don’t try everything blindly you prune bad choices early.

Think of it like:

“Try something, go deep. If it doesn’t work, undo and try something else.”

10. DFS & BFS, When You’re Exploring a Grid, Graph, or Connections

My Struggle:

I got a problem that said:

“Count the number of islands in a grid of 0s and 1s.

I was totally confused. What even is an island? How do I find which 1s are connected?

I thought maybe I should scan the whole grid again and again. But then I saw a simple solution using DFS.

When to Use:

  • Grid or graph problems
  • When you need to explore all connected things
  • Questions like: “Find all paths”, “Count components”, “Spread fire”, “Flood fill”, etc.

How It Works:

DFS (Depth First Search):

  • Goes as deep as possible first, like diving straight into one path.
  • Usually uses recursion or a stack

BFS (Breadth First Search):

  • Explores level by level, like throwing waves.
  • Usually uses a queue

Example, Number of Islands

You have:

Copygrid = [
  [1,1,0],
  [1,0,0],
  [0,0,1]
]

There are 2 islands:

  • One at top-left (all connected 1s)
  • One at bottom-right (single 1)

You pick any unvisited 1, and spreadusing DFS or BFS to mark all connected 1s.

Real Use-Cases:

  • Maze solver
  • Google Maps path finding
  • Word Search
  • Finding friend groups in social networks
  • Fire spreading in forest simulations

Why It’s Important:

Because many real-world systems (like social networks, cities, mazes) can be modeled as graphs.

Once you know DFS and BFS any grid or network-type problem becomes easy to think through.

11. Union Find, When You Want to Group Things Without Loops

My Struggle:

I saw a problem:

“Check if adding a connection creates a cycle.

I had no idea how to do this without building a full graph.

Then I learned about Union Find (also called Disjoint Set Union or DSU).

It’s like a smart way to keep track of which things belong together.

When to Use:

  • When you need to group things
  • When the question says: “Are A and B connected?”
  • When checking for cycles in undirected graphs

How It Works:

Each element starts in its own group.

You use two functions:

  1. Find: What is the “leader” (parent) of this group?
  2. Union: Combine two groups into one

Use a parent[] array for this.

Example:

Let’s say:

CopyConnections = [ (1, 2), (2, 3), (4, 5), (3, 1) ]

You start by making:

Copyparent[1] = 1  
parent[2] = 2  
parent[3] = 3  
parent[4] = 4  
parent[5] = 5

Now:

  • Union(1, 2) → now 2 follows 1
  • Union(2, 3) → now 3 follows 1
  • Now try Union(3, 1) → both already connected → cycle

That’s how you catch a cycle!

Why It’s Useful:

Because it’s fast and memory-efficient. You don’t need full graph logic. You just track which group each item belongs to.

Used in:

  • Kruskal’s Algorithm (Minimum Spanning Tree)
  • Friend circles / social groups
  • Connected components in networks

12. Topological Sort, When One Thing Must Happen Before Another

My Struggle:

I was asked:

“You have some courses to complete. Some courses need other courses to be done first. Find a valid order to complete all.

This confused me. I tried brute-force, but it didn’t work.

Then I learned this amazing trick: Topological Sort

When to Use:

  • When you’re given dependencies or “A must come before B”
  • Usually for schedulingtask ordercourse planning
  • You’re working with a Directed Acyclic Graph (DAG)

How It Works:

You build a graph where:

  • Each node is a task
  • An edge from A → B means “A must come before B”

Then use:

  • Kahn’s Algorithm (BFS-based)
  • OR DFS with stack to build the order

Example, Course Schedule

Let’s say:

CopyCourses: A, B, C  
Prerequisites: A → B, B → C

Valid order: A → B → C

Steps:

  • Build graph
  • Count how many incoming edges each node has (called indegree)
  • Start with courses having 0 prerequisites
  • Process them, reduce indegrees of their children
  • If any node’s indegree becomes 0, add it to the queue

Why It’s Powerful:

Because you can turn a mess of tasks into a clean order as long as there’s no cycle.

It’s used in:

  • Build systems (like compiling code)
  • Course planners
  • Job/task schedulers
  • Dependency managers (npm, Maven)

13. Greedy Algorithm, When You Pick the Best Step Right Now and Trust It Works Out

My Struggle:

I got a question:

“You’re given start and end times of meetings. What’s the maximum number of meetings you can attend without overlaps?

I thought: “Let’s try all combinations.” But that was super slow.

Then I read about Greedy Algorithmsmake the best local choice at each step, and you’ll often get the best global result.

When to Use:

  • When you can sort things and decide one-by-one
  • When there’s a clear “best” or “lowest cost” at each step
  • When you need to maximize or minimize something

How It Works:

Greedy means:

“At every step, pick the option that looks best at that moment.

You don’t backtrack. You trust your choice and move forward.

Example, Meeting Rooms

Meetings:

Copy[ (1, 4), (2, 5), (4, 7), (6, 8) ]

Sort by end time:

Copy[ (1, 4), (4, 7), (6, 8), (2, 5) ]

Start picking:

  • Pick (1, 4)
  • Next is (4, 7) → doesn’t overlap
  • Then (6, 8) → overlaps →
  • Done!

Answer: 2 meetings

Why It Works:

Because you don’t need to try all options you just make smart choices using sort + loop.

Other examples:

  • Activity selection
  • Fractional knapsack
  • Jump game
  • Gas station problems

14. Stack / Monotonic Stack When You Need to Track Previous or Next Bigger/Smaller Thing

My Struggle:

I got this question:

“For each day, tell me how many days to wait until a warmer temperature.”

My first try: nested loops compare today with every day after. Too slow.

Then I saw this new idea Monotonic Stack.

When to Use:

  • When you’re asked to find: “next greater”, “previous smaller”, etc.
  • When you need to track a history(like brackets, changes, or reversals)
  • Common in array problems

How It Works:

You keep a stack of useful values.

Let’s say you want to find the next greater number for each element.

Copyarr = [2, 1, 3]

You push 2, then 1 — when you see 3, it’s greater than both, so:

  • 1 → next greater = 3
  • 2 → next greater = 3
  • 3 → no greater after it

Use stack to maintain values in decreasing order (monotonic).

Classic Use Cases:

  • Next Greater Element
  • Daily Temperatures
  • Histogram Largest Rectangle
  • Valid Parentheses
  • Undo actions / editor history

Why It’s Useful:

Because it remembers what came before in a smart way. And avoids brute-force checking every pair.

15. Trie When You Want to Store or Search Words Quickly

My Struggle:

I was trying to build an autocomplete feature. I used an array or HashMap of words, and did “startsWith()” search. It worked… but it got slow with 1000s of words.

Then I found Trie (prefix tree) a tree where each level is one letter.

When to Use:

  • When you’re dealing with a dictionary of words
  • And you need to insert, search, or autocomplete efficiently
  • Any problem with prefixes

How It Works:

You build a tree where:

  • Each node is a letter
  • Paths form words
  • Every word ends with a special “end” marker

Example: Insert “cat” and “cap” into trie:

Copy        c
       /
      a
     / \
    t   p

Now:

  • Search “cat”? → yes
  • Search “cab”? → no
  • StartsWith “ca”? → yes

Why It’s Amazing:

Because it shares letters between words, so it’s fast and memory-friendly.

Used in:

  • Word suggestions
  • Spell checking
  • Phone contact search
  • Google-like autocomplete

16. Kadane’s Algorithm, When You Need the Max Sum Subarray

My Struggle:

I was given:

“Find the maximum sum of any subarray in a list of numbers (positive and negative).

I used two loops. Check every subarray. O(n²). Slow again.

Then I found Kadane’s Algorithm and it blew my mind.

When to Use:

  • When you want to find:
  • Maximum subarray sum
  • Maximum profit (buy/sell)
  • Especially with positive and negative numbers

How It Works:

You go through the array once.

At each step:

  • Either continue the current subarray
  • Or start fresh from this number

You keep tracking:

  • currentSum = max(num, currentSum + num)
  • maxSum = max(maxSum, currentSum)

Example:

Copyarr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]

Best subarray: [4, -1, 2, 1] → sum = 6

Kadane finds it in O(n) time only one loop!

Why It Works:

Because you don’t reset everything on a bad number. You just decide whether to continue or restart smartly.

One of the most elegant algorithms in DSA.

Final Thoughts: Pattern > Problem

When I started, I used to open a problem and just stare.

Now, I look and say:

“This is a sliding window problem”

“Oh, looks like two pointers can solve this”

“This is definitely backtracking with pruning” …and just like that, I know how to begin.

Learning these 16 patterns changed everything for me.

Leave a Reply