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
  • Programming
  • Problem Solving
  • Coding
  • Algorithms
  • Data Structures

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
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)
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)
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!