- read the problem carefully
- clarify any doubts
- what is the type of the input?
- pseudocode => brute-force => optimize
- what you are trying to do?
- handle edge cases
- when using recursion, handle base cases
- read documentation
- recognize common problem-solving patterns:
- sliding window: use two pointers
- fast-slow pointers
- recognize when to use algorithms
- divide and conquer
- dynamic programming
- sorting
- recursion
- ask LLM
- use reasoning models for complex problems
- when greedy solution fails, recursion with memoization is a powerful fallback to explore all paths and find a global solution
- pay attention to the function signature
- what is the output?
- what is the input?
- what is the purpose of each input?
- are you using the correct types?
break a complex problem into smaller sub-problems, solve each independently, and combine the solutions to solve the original problem
break a problem into smaller sub-problems, solve each only once, and store the solutions to sub-problems to avoid redundant computation and optimize the solution
- typical example: fibonacci sequence
- normally uses a matrix to store solutions
store results of expensive function calls and returns cached result when the same input occurs again
@lru_cache(None): built-in python decorator that caches the results of function calls with a specific argument
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)without lru_cache:
def fibonacci(n, memo = {}):
if n in memo:
return memo[n]
if n == 0:
return 0
elif n == 1:
return 1
else:
result = fibonacci(n-1, memo) + fibonacci(n-2, memo)
memo[n] = result
return resultTODO
- use
mapto easily search elements - define the complement then search it
- if you want to get the complement but don't want to get the first occurrence, you can create a map where you only add an element after you find that the complement is equal to the number
- example:
[1, 2, 2, 3]target is 4- 1 in map | 2, 2, 3 remain
TODO
- if it's a common prefix, restrict the length of the loop
- the maximum length of the prefix is the length of the shortest word
- If you don't wish to backtrack to get to the first element of a linked list, save it at the start of the program
- Don't forget the ternary operator
a = b if a > b else c- to replace elements in-place, track index positions with an offset variable
- beware off-by-1 errors
TODO
- One line Python solution
- Use
list[-1]
- when it's hard to manipulate an array, consider reversing the order in which you manipulate it
- recursion is a way to call future iterations of DFS without having to create a data structure to store memory of all iterations
- identify points where the solution should change behavior
- that way, you can define the functions that will compute each part of the solution
- pay attention to the return type of the function
- it normally helps you start building the logic behind a recursive solution
- If not node: return depth
max(recursive_function(), recursive_function())- Convert number to str
- If the number is negative, it's not a palindrome
- For
i in length//2:- You don't need to pass through all characters
- linear time complexity
- constant extra space
- the memory used can't grow with the size of input
- fixed extra memory used
- not allowed: arrays/dictionaries/sets that grow with the input
- bitwise operations can be useful
- the solution uses xor
- 0 XOR num = num
- num XOR num = 0
- 8000 >> 3 = 1000
- 8000/(2^3)
- 1000 << 3 = 8000
- 1000 * (2^3)
- turtle and hare solution
- If you create 2 pointers: 1 fast (hare), 1 slow (turtle), and you are looking for a circle, the hare eventually will reach/be the turtle
- create
set - check if there's duplicate in set
- if not, add the current element to set
- if you want to separate the digits of a number in a list, you can convert the number to a string and
.append(int(char))into the list
n = 223 => digits = [2, 2, 3]- only store what is necessary
- if you need to check only the last difference during iteration, don't save all the differences in a list
- the base cases tell you how to start the function:
- what happens when input is empty?
- what happens when input is one element?
- the recursion happens when?
- the function's input format is a hint on how to solve the problem
- in python, you don't need a buffer to switch 2 variables' values
a, b = b, a