Below is a structured, visual, and templated explanation for core algorithmic patterns. Each includes:
- ✅ Problem Statement
- 🧠 Pattern / Strategy Used
- 🔍 Why that pattern works here
- ✍️ Pseudocode (before coding)
- 🧭 Flow (decision-making or diagram)
- 🔧 Code using
Input → Logic → Outputtemplate
🪟 1. Sliding Window – Max Sum of Subarray of Size K
✅ Problem:
Find the maximum sum of any subarray of size
kfrom a list of positive integers.
🧠 Pattern: Sliding Window
🔍 Why Sliding Window?
We can reuse previous calculations to avoid recalculating the sum for overlapping subarrays.
✍️ Pseudocode:
1. Initialize window_sum with sum of first k elements
2. max_sum = window_sum
3. Slide window from left to right:
- Subtract leftmost element
- Add new rightmost element
- Update max_sum
🧭 Flow:
[1, 2, 3, 4, 5], k = 3
Window 1: sum(1,2,3) = 6
Window 2: Remove 1, add 4 => sum = 9
Window 3: Remove 2, add 5 => sum = 12 (max)
🔧 Code:
def get_input():
return [1, 2, 3, 4, 5], 3
def process(arr_k):
arr, k = arr_k
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(k, len(arr)):
window_sum = window_sum - arr[i-k] + arr[i]
max_sum = max(max_sum, window_sum)
return max_sum
def show_result(output):
print("Max sum of subarray:", output)
def main():
data = get_input()
result = process(data)
show_result(result)
main()
🔁 2. Two Pointers – Remove Duplicates in Sorted Array
✅ Problem:
Remove duplicates in-place from a sorted array. Return the new length.
🧠 Pattern: Two Pointers
🔍 Why Two Pointers?
Track one slow pointer for the unique part, and one fast pointer for scanning.
✍️ Pseudocode:
1. If empty, return 0
2. Set slow = 0
3. Loop fast from 1 to end:
- if arr[fast] != arr[slow]:
slow += 1
arr[slow] = arr[fast]
4. Return slow + 1 (length of unique array)
🧭 Flow:
Input: [1,1,2,2,3]
S F
[1,2,2,2,3] → [1,2,3,...]
🔧 Code:
def get_input():
return [1, 1, 2, 2, 3]
def process(arr):
if not arr:
return 0
slow = 0
for fast in range(1, len(arr)):
if arr[fast] != arr[slow]:
slow += 1
arr[slow] = arr[fast]
return slow + 1
def show_result(output):
print("Length of unique array:", output)
def main():
data = get_input()
result = process(data)
show_result(result)
main()
🔍 3. Backtracking – Subsets of a List
✅ Problem:
Given a list of distinct integers, return all possible subsets (power set).
🧠 Pattern: Backtracking
🔍 Why Backtracking?
We build the decision tree of including or excluding each number.
✍️ Pseudocode:
1. Start with empty path []
2. At each step:
- Add current path to result
- Recurse for each remaining element:
→ Include element
→ Backtrack
🧭 Flow (for [1,2]):
[]
/ \
[1] []
/ \ \
[1,2] [1] [2]
🔧 Code:
def get_input():
return [1, 2]
def process(nums):
result = []
def backtrack(start, path):
result.append(path[:])
for i in range(start, len(nums)):
path.append(nums[i])
backtrack(i+1, path)
path.pop()
backtrack(0, [])
return result
def show_result(output):
print("All subsets:", output)
def main():
data = get_input()
result = process(data)
show_result(result)
main()
🧮 4. Dynamic Programming – Fibonacci with Memoization
✅ Problem:
Return the nth Fibonacci number.
🧠 Pattern: Dynamic Programming (Top-Down)
🔍 Why DP?
Repetitive subproblems — solve once, store result.
✍️ Pseudocode:
fib(n):
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fib(n-1) + fib(n-2)
return memo[n]
🧭 Flow:
fib(5) → fib(4) + fib(3)
→ fib(3) + fib(2) + fib(2) + fib(1)
→ reuse fib(2), fib(3) from memo
🔧 Code:
def get_input():
return 6
def process(n):
memo = {}
def fib(x):
if x in memo:
return memo[x]
if x <= 1:
return x
memo[x] = fib(x - 1) + fib(x - 2)
return memo[x]
return fib(n)
def show_result(output):
print("Fibonacci number is:", output)
def main():
data = get_input()
result = process(data)
show_result(result)
main()
⬜ 5. Matrix Traversal – Spiral Order
✅ Problem:
Return all elements of a matrix in spiral order.
🧠 Pattern: Matrix Traversal (Boundary shrink)
🔍 Why Matrix Traversal?
Use 4 boundaries: top, bottom, left, right.
✍️ Pseudocode:
while top <= bottom and left <= right:
→ Traverse top row
↓ Traverse right col
← Traverse bottom row
↑ Traverse left col
→ Shrink boundaries
🧭 Flow:
1 2 3
4 5 6
7 8 9
→ → →
↓ ↓
← ← ←
↑
🔧 Code:
def get_input():
return [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
def process(matrix):
res = []
top, bottom = 0, len(matrix) - 1
left, right = 0, len(matrix[0]) - 1
while top <= bottom and left <= right:
for i in range(left, right + 1): # Top row
res.append(matrix[top][i])
top += 1
for i in range(top, bottom + 1): # Right column
res.append(matrix[i][right])
right -= 1
if top <= bottom:
for i in range(right, left - 1, -1): # Bottom row
res.append(matrix[bottom][i])
bottom -= 1
if left <= right:
for i in range(bottom, top - 1, -1): # Left column
res.append(matrix[i][left])
left += 1
return res
def show_result(output):
print("Spiral order:", output)
def main():
data = get_input()
result = process(data)
show_result(result)
main()
Leave a Reply