Python Problem Solving Guide
Comprehensive Python guide for problem solving with important built-in functions, data structures, algorithms, and commonly used patterns for coding interviews and competitive programming.
Python is one of the most popular languages for problem solving and competitive programming. This guide covers essential Python syntax, built-in functions, data structures, and patterns commonly used in coding interviews and algorithm problems.
Basics & Setup
#!/usr/bin/env python3
Shebang line for Linux/Mac execution
# This is a comment
Multi-line comments:
'''
This is a multi-line comment
or docstring
'''
"""
Also used for docstrings
or multi-line comments
"""
x = 5
print(type(x))
Variables are dynamically typed
from typing import List, Dict, Tuple
Import type hints
Data Types & Variables
Numbers
x = 10
Integer
y = 3.14
Float
z = 2 + 3j
Complex number
abs(-5)
Absolute value (result: 5)
pow(2, 3)
Power (result: 8)
pow(2, 3, 5)
Power with modulo: (2**3) % 5 (result: 3)
round(3.14159, 2)
Round to 2 decimal places (result: 3.14)
divmod(17, 5)
Returns (quotient, remainder) (result: (3, 2))
max(1, 5, 3, 9)
Maximum value
min(1, 5, 3, 9)
Minimum value
sum([1, 2, 3, 4, 5])
Sum of list (result: 15)
Strings
s = "Hello World"
text = 'Single or double quotes work'
len(s)
Length of string (result: 11)
s.upper()
Convert to uppercase
s.lower()
Convert to lowercase
s.capitalize()
Capitalize first letter
s.title()
Title case (capitalize each word)
s.split()
Split by whitespace → ["Hello", "World"]
s.split(',')
Split by comma
''.join(['a', 'b', 'c'])
Join list into string → "abc"
s.replace('World', 'Python')
Replace substring → "Hello Python"
s.find('World')
Find index of substring (result: 6)
s.startswith('Hello')
Check if starts with (result: True)
s.endswith('World')
Check if ends with (result: True)
'World' in s
Check if contains substring (result: True)
s.strip()
Remove leading/trailing whitespace
s.count('l')
Count occurrences (result: 3)
f"Hello {name}"
F-strings (formatted string literals)
"Hello {}".format(name)
Old-style string formatting
Lists & Arrays
List Creation & Access
lst = [1, 2, 3, 4, 5]
Create list
lst = list(range(1, 6))
Create list 1 to 5
lst = [0] * 5
Create list with 5 zeros → [0, 0, 0, 0, 0]
len(lst)
List length
lst[0]
Access first element
lst[-1]
Access last element
lst[1:4]
Slice from index 1 to 3 (exclusive end) → [2, 3, 4]
lst[::2]
Every 2nd element → [1, 3, 5]
lst[::-1]
Reverse list → [5, 4, 3, 2, 1]
lst[1:]
From index 1 to end → [2, 3, 4, 5]
lst[:3]
From start to index 2 → [1, 2, 3]
List Operations
lst.append(6)
Add to end
lst.extend([6, 7, 8])
Add multiple elements
lst.insert(0, 0)
Insert at specific index
lst.pop()
Remove and return last element
lst.pop(0)
Remove and return element at index
lst.remove(3)
Remove first occurrence of value
lst.clear()
Remove all elements
index = lst.index(3)
Find index of element
count = lst.count(2)
Count occurrences
lst.sort()
Sort in-place (ascending)
lst.sort(reverse=True)
Sort descending
sorted(lst)
Return new sorted list (doesn't modify original)
lst.reverse()
Reverse in-place
lst.copy()
Create shallow copy
lst1 + lst2
Concatenate lists
lst * 3
Repeat list 3 times
List Comprehensions
[x for x in range(1, 6)]
List comprehension → [1, 2, 3, 4, 5]
[x * 2 for x in range(1, 6)]
Transform elements → [2, 4, 6, 8, 10]
[x for x in range(1, 11) if x % 2 == 0]
With condition (even numbers) → [2, 4, 6, 8, 10]
[x for x in range(1, 11) if x % 2 == 0 and x > 5]
Multiple conditions → [6, 8, 10]
[[i, j] for i in range(1, 3) for j in range(1, 3)]
Nested loop → [[1, 1], [1, 2], [2, 1], [2, 2]]
[x if x % 2 == 0 else -x for x in range(1, 6)]
Ternary in comprehension → [-1, 2, -3, 4, -5]
Dictionaries
Dictionary Creation & Access
d = {'name': 'Adarsh', 'age': 25}
Create dictionary
d = dict(name='Adarsh', age=25)
Alternative syntax
d['name']
Access value by key
d.get('name')
Get value (returns None if not exists)
d.get('city', 'Unknown')
Get with default value
d['city'] = 'NYC'
Add or update key-value pair
len(d)
Number of key-value pairs
'name' in d
Check if key exists
d.keys()
Get all keys
d.values()
Get all values
d.items()
Get all key-value pairs as tuples
list(d.keys())
Convert to list
list(d.values())
Convert values to list
list(d.items())
Convert items to list of tuples
Dictionary Operations
d.pop('age')
Remove and return value for key
d.popitem()
Remove and return last inserted item
d.clear()
Remove all items
d.update({'age': 26, 'city': 'NYC'})
Update multiple values
d.copy()
Create shallow copy
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
d1.update(d2)
Merge dictionaries
{k: v for k, v in d.items()}
Dictionary comprehension
{k: v for k, v in d.items() if v > 20}
Dict comprehension with condition
{x: x**2 for x in range(1, 6)}
Create dict with comprehension → {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Sets
Set Creation & Operations
s = {1, 2, 3, 4, 5}
Create set (unordered, unique elements)
s = set([1, 2, 2, 3, 3])
Convert list to set (removes duplicates) → {1, 2, 3}
empty_set = set()
Empty set (not {}, which is dict)
len(s)
Set size
1 in s
Check membership
s.add(6)
Add element
s.remove(1)
Remove element (raises KeyError if not exists)
s.discard(1)
Remove element (no error if not exists)
s.pop()
Remove and return arbitrary element
s.clear()
Remove all elements
s1 = {1, 2, 3}
s2 = {3, 4, 5}
s1 & s2
Intersection → {3}
s1 | s2
Union → {1, 2, 3, 4, 5}
s1 - s2
Difference → {1, 2}
s1 ^ s2
Symmetric difference → {1, 2, 4, 5}
s1.issubset(s2)
Check if s1 is subset of s2
s1.issuperset(s2)
Check if s1 is superset of s2
s1.isdisjoint(s2)
Check if no common elements
{x for x in range(1, 6) if x % 2 == 0}
Set comprehension → {2, 4}
Tuples
Tuple Creation & Access
t = (1, 2, 3, 4, 5)
Create tuple (immutable)
t = tuple([1, 2, 3])
Convert list to tuple
t = (1,)
Single-element tuple (comma required)
t[0]
Access element (same as list)
t[1:3]
Slicing (same as list)
len(t)
Tuple length
1 in t
Check membership
t.count(2)
Count occurrences
t.index(3)
Find index
t1 + t2
Concatenate tuples
t * 3
Repeat tuple
a, b, c = (1, 2, 3)
Tuple unpacking
a, *rest, z = [1, 2, 3, 4, 5]
Unpacking with * (a=1, rest=[2,3,4], z=5)
Common Built-in Functions for Problem Solving
Iteration Functions
for i, value in enumerate([10, 20, 30]):
print(i, value)
Loop with index (0, 10), (1, 20), (2, 30)
list(range(1, 6))
Range from 1 to 5 → [1, 2, 3, 4, 5]
list(range(0, 10, 2))
Range with step → [0, 2, 4, 6, 8]
for a, b in zip([1, 2, 3], ['a', 'b', 'c']):
print(a, b)
Zip lists together
for val in reversed([1, 2, 3]):
print(val)
Iterate in reverse order
for val in sorted([3, 1, 2]):
print(val)
Iterate in sorted order
for val in filter(lambda x: x > 2, [1, 2, 3, 4]):
print(val)
Filter values (3, 4)
list(map(lambda x: x**2, [1, 2, 3]))
Map function over list → [1, 4, 9]
all([True, True, True])
Check if all elements are True (result: True)
any([False, False, True])
Check if any element is True (result: True)
Type Checking & Conversion
type(x)
Get type of variable
isinstance(x, int)
Check if variable is type
int(3.14)
Convert to integer
float('3.14')
Convert to float
str(123)
Convert to string
list('abc')
Convert string to list → ['a', 'b', 'c']
dict([('a', 1), ('b', 2)])
Convert list of tuples to dict
bool(1)
Convert to boolean (result: True)
ord('A')
Get ASCII value (result: 65)
chr(65)
Get character from ASCII (result: 'A')
hex(255)
Convert to hexadecimal (result: '0xff')
bin(5)
Convert to binary (result: '0b101')
oct(8)
Convert to octal (result: '0o10')
Sorting & Priority
sorted([3, 1, 4, 1, 5, 9])
Sort list → [1, 1, 3, 4, 5, 9]
sorted([3, 1, 4], reverse=True)
Sort descending → [4, 3, 1]
sorted([(1, 3), (1, 1), (2, 2)], key=lambda x: x[1])
Sort by second element
data = [('Alice', 25), ('Bob', 20), ('Charlie', 25)]
sorted(data, key=lambda x: (x[1], x[0]))
Multi-level sort (by age then name)
max([1, 5, 3, 2])
Maximum value (result: 5)
min([1, 5, 3, 2])
Minimum value (result: 1)
max([1, 5, 3, 2], key=lambda x: -x)
Maximum with custom key
from collections import Counter
Counter([1, 1, 2, 2, 2, 3])
Count frequencies → Counter({2: 3, 1: 2, 3: 1})
from heapq import heappush, heappop
Priority queue operations
Lambda & Anonymous Functions
lambda x: x * 2
Anonymous function that doubles
f = lambda x, y: x + y
Store lambda in variable
map(lambda x: x**2, [1, 2, 3])
Use lambda with map
filter(lambda x: x % 2 == 0, range(10))
Use lambda with filter
sorted([3, 1, 4], key=lambda x: -x)
Use lambda as sort key
Sorting Patterns
Sort List of Tuples
# Sort students by marks (descending)
def sort_by_mark(my_class):
return sorted(my_class, key=lambda x: x[0], reverse=True)
students = [(95, 'Alice'), (88, 'Bob'), (92, 'Charlie')]
sorted_by_mark = sort_by_mark(students)
Result: [(95, 'Alice'), (92, 'Charlie'), (88, 'Bob')]
# Sort students by name (ascending alphabetically)
def sort_by_name(my_class):
return sorted(my_class, key=lambda x: x[1])
sorted_by_name = sort_by_name(students)
Result: [(88, 'Bob'), (92, 'Charlie'), (95, 'Alice')]
# Combined: Sort by mark descending, then by name ascending
def sort_by_both(my_class):
return sorted(my_class, key=lambda x: (-x[0], x[1]))
students = [(95, 'Alice'), (92, 'Bob'), (95, 'Charlie')]
sorted_by_both(students)
Result: [(95, 'Alice'), (95, 'Charlie'), (92, 'Bob')]
Sort Dictionary by Values
data = {'apple': 5, 'banana': 2, 'cherry': 8}
# Sort by values (ascending)
sorted_dict = sorted(data.items(), key=lambda x: x[1])
Result: [('banana', 2), ('apple', 5), ('cherry', 8)]
# Sort by values (descending)
sorted_dict = sorted(data.items(), key=lambda x: x[1], reverse=True)
Result: [('cherry', 8), ('apple', 5), ('banana', 2)]
# Convert back to dictionary
dict(sorted(data.items(), key=lambda x: x[1], reverse=True))
Result: {'cherry': 8, 'apple': 5, 'banana': 2}
Sort List of Objects
class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks
def __repr__(self):
return f"Student({self.name}, {self.marks})"
students = [
Student("Alice", 95),
Student("Bob", 88),
Student("Charlie", 92)
]
# Sort by marks descending
sorted_students = sorted(students, key=lambda x: x.marks, reverse=True)
# Sort by name ascending
sorted_students = sorted(students, key=lambda x: x.name)
# Sort by marks then name
sorted_students = sorted(students, key=lambda x: (-x.marks, x.name))
Custom Sorting with Multiple Criteria
# Data: (priority, name, deadline)
tasks = [
(1, 'Task A', '2026-04-12'),
(3, 'Task B', '2026-04-10'),
(2, 'Task C', '2026-04-11'),
(1, 'Task D', '2026-04-15')
]
# Sort by priority (descending), then by deadline (ascending)
sorted_tasks = sorted(tasks, key=lambda x: (-x[0], x[2]))
# Instead of reverse tuples, use multiple sorts (stable sort)
sorted_tasks = tasks
sorted_tasks = sorted(sorted_tasks, key=lambda x: x[2]) # Sort by deadline
sorted_tasks = sorted(sorted_tasks, key=lambda x: x[0], reverse=True) # Then by priority
Common Problem-Solving Patterns
Find Duplicates
lst = [1, 2, 2, 3, 3, 3, 4]
len(lst) != len(set(lst))
Check if duplicates exist
duplicates = [x for x in set(lst) if lst.count(x) > 1]
Find all duplicates
from collections import Counter
duplicates = [k for k, v in Counter(lst).items() if v > 1]
More efficient way
Two Pointers
def two_sum(arr, target):
left, right = 0, len(arr) - 1
while left < right:
s = arr[left] + arr[right]
if s == target:
return [left, right]
elif s < target:
left += 1
else:
right -= 1
return []
Sliding Window
def max_sum_window(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
Union Find (Disjoint Set)
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
px, py = self.find(x), self.find(y)
if px == py:
return
if self.rank[px] < self.rank[py]:
px, py = py, px
self.parent[py] = px
if self.rank[px] == self.rank[py]:
self.rank[px] += 1
DFS (Depth-First Search)
def dfs(graph, node, visited=None):
if visited is None:
visited = set()
visited.add(node)
print(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
graph = {1: [2, 3], 2: [4], 3: [4], 4: []}
dfs(graph, 1)
BFS (Breadth-First Search)
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
node = queue.popleft()
print(node)
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
bfs(graph, 1)
Binary Search
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
Important Standard Libraries
collections Module
from collections import Counter, defaultdict, deque, namedtuple
Counter([1, 1, 2, 2, 2])
Count frequencies
defaultdict(list)
Dictionary with default value
deque([1, 2, 3])
Double-ended queue
namedtuple('Point', ['x', 'y'])
Named tuple for cleaner code
itertools Module
from itertools import combinations, permutations, product
list(combinations([1, 2, 3], 2))
All 2-combinations → [(1, 2), (1, 3), (2, 3)]
list(permutations([1, 2, 3], 2))
All 2-permutations → [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
list(product([1, 2], [3, 4]))
Cartesian product → [(1, 3), (1, 4), (2, 3), (2, 4)]
from itertools import chain
list(chain([1, 2], [3, 4]))
Flatten iterables → [1, 2, 3, 4]
from itertools import repeat
list(repeat(0, 5))
Repeat element → [0, 0, 0, 0, 0]
math Module
import math
math.sqrt(16)
Square root (result: 4.0)
math.ceil(3.2)
Round up (result: 4)
math.floor(3.8)
Round down (result: 3)
math.gcd(12, 18)
Greatest common divisor (result: 6)
math.lcm(12, 18)
Least common multiple (result: 36)
math.factorial(5)
Factorial 5! = 120
math.pi
Pi constant (3.14159...)
math.e
Euler's number
math.inf
Infinity
math.log(8, 2)
Logarithm base 2
File I/O
with open('file.txt', 'r') as f:
content = f.read()
Read entire file
with open('file.txt', 'r') as f:
lines = f.readlines()
Read all lines
with open('file.txt', 'w') as f:
f.write('Hello')
Write to file (overwrite)
with open('file.txt', 'a') as f:
f.write('World')
Append to file
for line in open('file.txt'):
print(line.strip())
Read line by line
Error Handling
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero")
try:
lst[100]
except IndexError as e:
print(f"Index error: {e}")
try:
int('abc')
except ValueError:
print("Invalid integer")
try:
risky_operation()
except Exception as e:
print(f"Error: {e}")
finally:
print("Cleanup code")
More Python concepts and patterns will be added as needed!