logo

Interview Simplified

DSA Concepts

Quick reference guide for Python Data Structure and Algorithms.

🛠 DSA

List

# 1) Creating lists
empty_list = []
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]

# 2) Accessing elements (0-indexed)
print(numbers[0])  # First element: 1
print(numbers[-1]) # Last element: 5

# 3) Slicing [start:end:step]
print(numbers[1:4])    # [2, 3, 4]
print(numbers[::2])    # [1, 3, 5]
print(numbers[::-1])   # [5, 4, 3, 2, 1] (reversed)

# 4) Common operations
numbers.append(6)      # Add to end: [1, 2, 3, 4, 5, 6]
numbers.insert(0, 0)   # Insert at index: [0, 1, 2, 3, 4, 5, 6]
numbers.pop()          # Remove and return last element: 6, list becomes [0, 1, 2, 3, 4, 5]
numbers.pop(0)         # Remove at index: 0, list becomes [1, 2, 3, 4, 5]
numbers.remove(3)      # Remove by value: [1, 2, 4, 5]

# 5) List methods
nums = [3, 1, 4, 1, 5, 9]
nums.sort()            # Sort in-place: [1, 1, 3, 4, 5, 9]
nums.reverse()         # Reverse in-place: [9, 5, 4, 3, 1, 1]
print(nums.count(1))   # Count occurrences: 2
print(nums.index(5))   # Find index of value: 1

# 6) List comprehensions
squares = [x**2 for x in range(5)]              # [0, 1, 4, 9, 16]
even_squares = [x**2 for x in range(10) if x % 2 == 0]  # [0, 4, 16, 36, 64]

# 7) Nested lists (matrices)
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
print(matrix[1][2])    # Access element at row 1, col 2: 6

Sets

# 1) Creating sets
empty_set = set()            # Empty set (cannot use {} as that creates an empty dict)
fruits = {'apple', 'banana', 'cherry'}
numbers = set([1, 2, 3, 2, 1])  # From iterable - duplicates removed: {1, 2, 3}

# 2) Basic operations
print(len(fruits))           # Number of elements: 3
print('apple' in fruits)     # Membership testing: True

# 3) Adding and removing elements
fruits.add('orange')         # Add a single element
fruits.update(['mango', 'grapes'])  # Add multiple elements
fruits.remove('banana')      # Remove element (raises KeyError if not found)
fruits.discard('kiwi')       # Remove if present (no error if not found)
popped = fruits.pop()        # Remove and return an arbitrary element
fruits.clear()               # Remove all elements

# 4) Set operations
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

union = set1 | set2          # Union: {1, 2, 3, 4, 5, 6, 7, 8}
# Alternatively: set1.union(set2)

intersection = set1 & set2   # Intersection: {4, 5}
# Alternatively: set1.intersection(set2)

difference = set1 - set2     # Difference: {1, 2, 3}
# Alternatively: set1.difference(set2)

sym_diff = set1 ^ set2      # Symmetric difference: {1, 2, 3, 6, 7, 8}
# Alternatively: set1.symmetric_difference(set2)

# 5) Subset and superset
set3 = {1, 2}
print(set3.issubset(set1))   # True: set3 ⊆ set1
print(set1.issuperset(set3)) # True: set1 ⊇ set3
print(set1.isdisjoint(set3)) # False: set1 and set3 have elements in common

# 6) Set comprehensions
evens = {x for x in range(10) if x % 2 == 0}  # {0, 2, 4, 6, 8}

# 7) Frozen sets (immutable sets)
frozen = frozenset(['a', 'b', 'c'])
# frozen.add('d')  # This would raise an AttributeError - cannot modify

Dictionaries

# 1) Creating dictionaries
empty_dict = {}
person = {'name': 'Alice', 'age': 30, 'city': 'New York'}
user = dict(username='john_doe', email='john@example.com')  # Alternative creation

# 2) Accessing elements
print(person['name'])        # Access by key: 'Alice'
print(person.get('age'))     # Safe access: 30
print(person.get('phone', 'Not found'))  # With default value: 'Not found'

# 3) Adding and modifying elements
person['phone'] = '555-1234'  # Add new key-value pair
person['age'] = 31            # Modify existing value

# 4) Removing elements
del person['city']            # Remove key-value pair
phone = person.pop('phone')   # Remove and return value: '555-1234'
last_item = person.popitem()  # Remove and return last item as tuple: ('age', 31)
person.clear()                # Remove all items

# 5) Dictionary methods
user_info = {'name': 'Bob', 'role': 'admin'}

keys = user_info.keys()       # View of keys: dict_keys(['name', 'role'])
values = user_info.values()   # View of values: dict_values(['Bob', 'admin'])
items = user_info.items()     # View of key-value pairs: dict_items([('name', 'Bob'), ('role', 'admin')])

# These views are dynamic and reflect changes to the dictionary
user_info['department'] = 'IT'
print(list(keys))             # ['name', 'role', 'department']

# 6) Dictionary comprehensions
squares = {x: x**2 for x in range(5)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 7) Nested dictionaries
employees = {
    'alice': {'id': 101, 'dept': 'HR', 'salary': 75000},
    'bob': {'id': 102, 'dept': 'IT', 'salary': 80000}
}
print(employees['bob']['salary'])  # 80000

# 8) Merging dictionaries
defaults = {'theme': 'light', 'language': 'en'}
user_prefs = {'theme': 'dark'}

# Python 3.9+
merged = defaults | user_prefs  # {'theme': 'dark', 'language': 'en'}

# Earlier versions
merged = {**defaults, **user_prefs}
# Or
merged = defaults.copy()
merged.update(user_prefs)

# 9) Default dictionaries (from collections)
from collections import defaultdict
word_count = defaultdict(int)  # Default value for missing keys is 0
for word in ['apple', 'banana', 'apple', 'orange']:
    word_count[word] += 1
print(dict(word_count))  # {'apple': 2, 'banana': 1, 'orange': 1}

Comprehensions

# Comprehensions are concise ways to create collections in Python

# 1) List comprehensions
numbers = [1, 2, 3, 4, 5]

# Basic syntax: [expression for item in iterable]
squares = [x**2 for x in numbers]
print(squares)  # [1, 4, 9, 16, 25]

# With conditional: [expression for item in iterable if condition]
even_squares = [x**2 for x in numbers if x % 2 == 0]
print(even_squares)  # [4, 16]

# With if-else in expression: [true_expr if condition else false_expr for item in iterable]
parity = ['even' if x % 2 == 0 else 'odd' for x in numbers]
print(parity)  # ['odd', 'even', 'odd', 'even', 'odd']

# 2) Dictionary comprehensions

# Basic syntax: {key_expr: value_expr for item in iterable}
square_dict = {x: x**2 for x in range(1, 6)}
print(square_dict)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# With conditional: {key_expr: value_expr for item in iterable if condition}
even_squares = {x: x**2 for x in range(1, 11) if x % 2 == 0}
print(even_squares)  # {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

# Convert between dictionaries
prices = {'apple': 0.40, 'banana': 0.50, 'orange': 0.45}
double_prices = {fruit: price*2 for fruit, price in prices.items()}
print(double_prices)  # {'apple': 0.8, 'banana': 1.0, 'orange': 0.9}

# 3) Set comprehensions

# Basic syntax: {expression for item in iterable}
unique_squares = {x**2 for x in [1, 2, 2, 3, 3, 3]}
print(unique_squares)  # {1, 4, 9}

# With conditional: {expression for item in iterable if condition}
vowels = {char for char in 'hello world' if char in 'aeiou'}
print(vowels)  # {'e', 'o'}

# 4) Generator expressions
# Similar to list comprehensions but use () and create generators (memory efficient)

# Basic syntax: (expression for item in iterable)
square_gen = (x**2 for x in numbers)
print(next(square_gen))  # 1
print(next(square_gen))  # 4

# With conditional: (expression for item in iterable if condition)
even_squares_gen = (x**2 for x in numbers if x % 2 == 0)
print(list(even_squares_gen))  # [4, 16]

# 5) Nested comprehensions

# Creating a flattened list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Creating a matrix (2D list)
grid = [[x + y for x in range(3)] for y in range(3)]
print(grid)  # [[0, 1, 2], [1, 2, 3], [2, 3, 4]]

🚌 Built-In Functions

len()

# 1) Length of a string
text = "Hello, world!"
print(len(text))
# 13

# 2) Number of items in a list
fruits = ["apple", "banana", "cherry"]
print(len(fruits))
# 3

# 3) Size of a dictionary
user = {"name": "Alice", "age": 30, "email": "alice@example.com"}
print(len(user))
# 3

# 4) Length of a tuple
coordinates = (10, 20, 30, 40)
print(len(coordinates))
# 4

# 5) Number of items in a set
unique_numbers = {1, 2, 3, 4, 5, 5, 4, 3}
print(len(unique_numbers))
# 5 (duplicates are removed in sets)

max()

# 1) Basic usage with a list
nums = [3, 10, 1]
print(max(nums))
# 10

# 2) With multiple separate arguments
print(max(5, 2, 9, 4))
# 9

# 3) Using key to choose the "largest" by a property (longest string)
words = ["cat", "hippopotamus", "dog"]
print(max(words, key=len))
# hippopotamus

# 4) Max on a list of dicts by a field
students = [
    {"name": "Ana", "score": 88},
    {"name": "Ben", "score": 92},
    {"name": "Chad", "score": 85},
]
top = max(students, key=lambda s: s["score"])
print(top["name"], top["score"])
# Ben 92

min()

# 1) Basic usage with a list
nums = [3, 10, 1, 5]
print(min(nums))
# 1

# 2) With multiple separate arguments
print(min(5, 2, 9, 4))
# 2

# 3) Using key to choose the "smallest" by a property (shortest string)
words = ["cat", "hippopotamus", "dog", "a"]
print(min(words, key=len))
# a

# 4) Min on a list of dicts by a field
students = [
    {"name": "Ana", "score": 88},
    {"name": "Ben", "score": 92},
    {"name": "Chad", "score": 85},
]
lowest = min(students, key=lambda s: s["score"])
print(lowest["name"], lowest["score"])
# Chad 85

abs()

# Returns the absolute value of a number
print(abs(-5))
# 5

print(abs(3.14))
# 3.14

print(abs(-2.718))
# 2.718

# Useful in calculating distances
point1 = (1, 2)
point2 = (4, 6)
distance_x = abs(point2[0] - point1[0])
print(distance_x)
# 3

sum()

# 1) Basic usage with a list of numbers
numbers = [1, 2, 3, 4, 5]
print(sum(numbers))
# 15

# 2) With a start value (adds this to the sum)
print(sum(numbers, 10))
# 25

# 3) Sum with generator expressions
print(sum(x*2 for x in range(5)))
# 20 (0*2 + 1*2 + 2*2 + 3*2 + 4*2)

# 4) Summing floats
floats = [1.5, 2.5, 3.5]
print(sum(floats))
# 7.5

ord()

# Returns the Unicode code point for a character
print(ord('A'))
# 65

print(ord('a'))
# 97

print(ord('🙂'))
# 128578

# Useful for character manipulation and encryption
def simple_cipher(text, shift):
    encrypted = ''
    for char in text:
        if char.isalpha():
            # Shift the character by the specified amount
            code = ord(char) + shift
            encrypted += chr(code)
        else:
            encrypted += char
    return encrypted

print(simple_cipher('abc', 1))
# bcd