Time & Space Complexity

Common time complexities: O(1), O(log n), O(n), O(n log n), and O(n²)

Time Complexities

O(log n) is when size is reduced by a constant fraction each step, like binary search

O(n log n) is when it is turned into a subproblem that is solved independently, like merge sort or when there is an O(n) part and recursion part

For space complexities:

O(1) uses a constant amount of extra space

O(log n) typically for recursion, it is space proportional to the logarithm of the input

O(n) the space proportional to the input size

O(n log n) certain divide and conquer algos that use extra data structures

O(n²) uses the square of the input size

(2^n) when the space grows with the input size

Pandas Crash course

# First few rows
print(df.head())
# Last few rows
print(df.tail())
# Summary of the DataFrame
print(df.info())
# Descriptive statistics
print(df.describe())
# Selecting a single column
print(df['Name'])
# Selecting multiple columns
print(df[['Name', 'Age']])
# Selecting rows by position
print(df.iloc[0:2])  # First two rows
# Selecting rows by label
print(df.loc[0:2])  # Rows with index 0 to 2
# Rows where Age is greater than 30
print(df[df['Age'] > 30])
# Rows where City is 'Berlin'
print(df[df['City'] == 'Berlin'])
# Adding a new column
df['Salary'] = [50000, 60000, 70000, 80000]
print(df)
# Modifying a column
df['Age'] = df['Age'] + 1
print(df)
# Deleting a column
df.drop('Salary', axis=1, inplace=True)
print(df)

# Checking for missing values
print(df.isnull().sum())

# Dropping rows with missing values
df.dropna(inplace=True)
# Filling missing values
df.fillna(0, inplace=True)
# Creating a pivot table
pivot_table = df.pivot_table(values='Age', index='City', aggfunc='mean')
print(pivot_table)

# Group by City and calculate mean Age
print(df.groupby('City')['Age'].mean())

# Merge two DataFrames on a common column
df1 = pd.DataFrame({
    'Name': ['John', 'Anna', 'Peter', 'Linda'],
    'Age': [28, 24, 35, 32]
})
df2 = pd.DataFrame({
    'Name': ['John', 'Anna', 'Peter', 'Linda'],
    'Salary': [50000, 60000, 70000, 80000]
})
merged_df = pd.merge(df1, df2, on='Name')
print(merged_df)

Single Bracket: When you use a single bracket with a column name, pandas returns a Series.

Double Bracket: When using double brackets, you pass a list of column names to pandas, which returns a DataFrame containing only those columns.

range(1, 12) produces [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].

Division

7%3 = 1 (remainder)

7&3 = bitwise and operation so it will be 3