From 11979ecfb96277104c3575dc3d50977de131365d Mon Sep 17 00:00:00 2001 From: Maverick Espinosa Date: Fri, 19 Dec 2025 11:55:04 -0700 Subject: [PATCH 1/4] Checkpoint from VS Code for coding agent session --- .../0_Problem_Solving_Patterns.ipynb | 24 +- Datastructures + Algorithms/10_graph.ipynb | 0 .../1d_hash_table_dictionary_hash_map.ipynb | 892 +++++++++++++++++- Datastructures + Algorithms/7_heap.ipynb | 176 ++++ Datastructures + Algorithms/8_graph.ipynb | 51 + Datastructures + Algorithms/8_hash_set.ipynb | 0 Datastructures + Algorithms/9_heap.ipynb | 0 7 files changed, 1138 insertions(+), 5 deletions(-) delete mode 100644 Datastructures + Algorithms/10_graph.ipynb create mode 100644 Datastructures + Algorithms/7_heap.ipynb create mode 100644 Datastructures + Algorithms/8_graph.ipynb delete mode 100644 Datastructures + Algorithms/8_hash_set.ipynb delete mode 100644 Datastructures + Algorithms/9_heap.ipynb diff --git a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb index 126da8a..58f8e40 100644 --- a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb +++ b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb @@ -405,10 +405,12 @@ "\n", "Input: s= \"hello\"\n", "Output: \"holle\"\n", + "\n", "Example 2:\n", "\n", "Input: s= \"AEIOU\"\n", "Output: \"UOIEA\"\n", + "\n", "Example 3:\n", "\n", "Input: s= \"DesignGUrus\"\n", @@ -421,21 +423,35 @@ "\n", "# Understanding\n", "# - Reiterate Question + requirements to ensure you understand the problem\n", + "# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the vowel found at len - index of current vowel in the list\n", "\n", "# Approach\n", - "# - Describe your approach to solving the problem.\n", + "# - Describe your approach + psuedocode to solving the problem.\n", + "# Brute Force:\n", + "# 1. Scan through the input string\n", + "# 2. check if char lowercased in vowel set\n", + "# a. if not add to output string\n", + "# b. if yes find index of vowel, add element in vowel set with index len - index of vowel to output string\n", + "# 3. return string\n", "\n", "# Complexity \n", "# - Add your time complexity here\n", - "\n", + "# O(n) to loop through input string\n", "# - Add your space complexity here\n", + "# O(1) since max 5 vowels to store in set ds\n", + "\n", + "# Optimized:\n", + "\n", "\n", - "# PsuedoCode\n", - "# - Describe solution in psuedocode\n", "\n", "class Solution:\n", " def reverseVowels(self, s: str) -> str:\n", " # TODO: Write your code here\n", + " vowels = list(\"aeiou\")\n", + " for i, char in enumerate(s.lower()):\n", + " if char in vowels:\n", + " s[i] = vowels[len(vowels) - i]\n", + " \n", " return s" ] }, diff --git a/Datastructures + Algorithms/10_graph.ipynb b/Datastructures + Algorithms/10_graph.ipynb deleted file mode 100644 index e69de29..0000000 diff --git a/Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb b/Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb index 92c1dfa..d9fc4a8 100644 --- a/Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb +++ b/Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb @@ -8,6 +8,122 @@ "# Implementations" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "e48db800", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "### Hash Table / Dictionary - Key-Value Mapping\n", + "\n", + "- Unordered collection of key-value pairs\n", + "- O(1) average case lookup, insertion, deletion\n", + "- Keys must be hashable (immutable): strings, numbers, tuples\n", + "- Values can be any type\n", + "- Python's dict is a hash table implementation\n", + "\"\"\"\n", + "# (Code)\n", + "\n", + "# Empty dictionary\n", + "d = {}\n", + "\n", + "# Dictionary with initial values\n", + "d = {\"name\": \"Alice\", \"age\": 30, \"city\": \"NYC\"}\n", + "\n", + "# Dictionary from pairs\n", + "d = dict([(\"x\", 1), (\"y\", 2)])\n", + "\n", + "# Dictionary comprehension\n", + "d = {i: i**2 for i in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}\n", + "\n", + "# Nested dictionary\n", + "person = {\n", + " \"name\": \"Bob\",\n", + " \"age\": 25,\n", + " \"address\": {\"street\": \"123 Main\", \"city\": \"LA\"}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "ba2eb704", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HashTable({'apple': 5, 'banana': 3, 'cherry': 8})\n", + "5\n", + "True\n", + "3\n", + "2\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Complete Dictionary Implementation (Interview-Ready)\n", + "\"\"\"\n", + "class HashTable:\n", + " def __init__(self):\n", + " self.table = {}\n", + " \n", + " def put(self, key, value):\n", + " \"\"\"Insert or update key-value pair - O(1) average\"\"\"\n", + " self.table[key] = value\n", + " \n", + " def get(self, key):\n", + " \"\"\"Retrieve value by key - O(1) average\"\"\"\n", + " if key not in self.table:\n", + " raise KeyError(f\"Key '{key}' not found\")\n", + " return self.table[key]\n", + " \n", + " def remove(self, key):\n", + " \"\"\"Delete key-value pair - O(1) average\"\"\"\n", + " if key not in self.table:\n", + " raise KeyError(f\"Key '{key}' not found\")\n", + " del self.table[key]\n", + " \n", + " def contains(self, key):\n", + " \"\"\"Check if key exists - O(1) average\"\"\"\n", + " return key in self.table\n", + " \n", + " def keys(self):\n", + " \"\"\"Get all keys - O(n)\"\"\"\n", + " return list(self.table.keys())\n", + " \n", + " def values(self):\n", + " \"\"\"Get all values - O(n)\"\"\"\n", + " return list(self.table.values())\n", + " \n", + " def items(self):\n", + " \"\"\"Get all key-value pairs - O(n)\"\"\"\n", + " return list(self.table.items())\n", + " \n", + " def size(self):\n", + " \"\"\"Return number of key-value pairs - O(1)\"\"\"\n", + " return len(self.table)\n", + " \n", + " def __repr__(self):\n", + " return f\"HashTable({self.table})\"\n", + "\n", + "# Usage\n", + "ht = HashTable()\n", + "ht.put(\"apple\", 5)\n", + "ht.put(\"banana\", 3)\n", + "ht.put(\"cherry\", 8)\n", + "print(ht) # HashTable({'apple': 5, 'banana': 3, 'cherry': 8})\n", + "print(ht.get(\"apple\")) # 5\n", + "print(ht.contains(\"banana\")) # True\n", + "print(ht.size()) # 3\n", + "ht.remove(\"banana\")\n", + "print(ht.size()) # 2" + ] + }, { "cell_type": "markdown", "id": "c11836b1", @@ -16,6 +132,353 @@ "# Methods / Operations" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "b066be66", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "### .get(key, default=None)\n", + "\n", + "- Retrieve value by key - O(1) average\n", + "- Returns default if key not found (safe)\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"name\": \"Alice\", \"age\": 30}\n", + "print(d.get(\"name\")) # \"Alice\"\n", + "print(d.get(\"city\")) # None\n", + "print(d.get(\"city\", \"Unknown\")) # \"Unknown\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f3118da7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "{'x': 1, 'y': 2, 'z': 3}\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### dict[key] / dict[key] = value\n", + "\n", + "- Direct access and assignment - O(1) average\n", + "- Raises KeyError if key doesn't exist on access\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"x\": 1, \"y\": 2}\n", + "print(d[\"x\"]) # 1\n", + "d[\"z\"] = 3 # Add new key\n", + "print(d) # {'x': 1, 'y': 2, 'z': 3}\n", + "# d[\"w\"] # KeyError: 'w'\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a234ed70", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['name', 'age', 'city'])\n", + "dict_values(['Alice', 30, 'NYC'])\n", + "dict_items([('name', 'Alice'), ('age', 30), ('city', 'NYC')])\n", + "['name', 'age', 'city']\n", + "['Alice', 30, 'NYC']\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### .keys() / .values() / .items()\n", + "\n", + "- Get all keys, values, or key-value pairs - O(n)\n", + "- Returns view objects (iterable)\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"name\": \"Alice\", \"age\": 30, \"city\": \"NYC\"}\n", + "print(d.keys()) # dict_keys(['name', 'age', 'city'])\n", + "print(d.values()) # dict_values(['Alice', 30, 'NYC'])\n", + "print(d.items()) # dict_items([('name', 'Alice'), ('age', 30), ('city', 'NYC')])\n", + "\n", + "# Convert to list if needed\n", + "print(list(d.keys())) # ['name', 'age', 'city']\n", + "print(list(d.values())) # ['Alice', 30, 'NYC']\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3f0ebf6d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n", + "False\n", + "True\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### in / not in\n", + "\n", + "- Check if key exists - O(1) average\n", + "- Much faster than checking values\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"a\": 1, \"b\": 2, \"c\": 3}\n", + "print(\"a\" in d) # True\n", + "print(\"x\" in d) # False\n", + "print(\"a\" not in d) # False\n", + "\n", + "# Check if value exists (slower - O(n))\n", + "print(1 in d.values()) # True\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "0661de68", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30\n", + "{'name': 'Alice'}\n", + "Unknown\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### .pop(key, default=None)\n", + "\n", + "- Remove and return value - O(1) average\n", + "- Returns default if key not found\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"name\": \"Alice\", \"age\": 30}\n", + "age = d.pop(\"age\")\n", + "print(age) # 30\n", + "print(d) # {'name': 'Alice'}\n", + "\n", + "# Pop with default (safe)\n", + "city = d.pop(\"city\", \"Unknown\")\n", + "print(city) # \"Unknown\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "165e179f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'a': 1, 'b': 20, 'c': 30}\n", + "{'a': 1, 'b': 20, 'c': 30, 'd': 40, 'e': 50}\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### .update(other)\n", + "\n", + "- Merge another dictionary or iterable - O(n)\n", + "- Overwrites existing keys\n", + "\"\"\"\n", + "# (Code)\n", + "d1 = {\"a\": 1, \"b\": 2}\n", + "d2 = {\"b\": 20, \"c\": 30}\n", + "d1.update(d2)\n", + "print(d1) # {'a': 1, 'b': 20, 'c': 30}\n", + "\n", + "# Update from iterable of pairs\n", + "d1.update([(\"d\", 40), (\"e\", 50)])\n", + "print(d1) # {'a': 1, 'b': 20, 'c': 30, 'd': 40, 'e': 50}\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "e554e206", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{}\n", + "0\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### .clear()\n", + "\n", + "- Remove all key-value pairs - O(n)\n", + "- Dictionary still exists but is empty\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"a\": 1, \"b\": 2}\n", + "d.clear()\n", + "print(d) # {}\n", + "print(len(d)) # 0\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4f2b973e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'a': 1, 'b': [2, 3, 4]}\n", + "{'a': 99, 'b': [2, 3, 4]}\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### .copy()\n", + "\n", + "- Create shallow copy - O(n)\n", + "- Modifications don't affect original\n", + "\"\"\"\n", + "# (Code)\n", + "original = {\"a\": 1, \"b\": [2, 3]}\n", + "copy_dict = original.copy()\n", + "copy_dict[\"a\"] = 99\n", + "copy_dict[\"b\"].append(4)\n", + "\n", + "print(original) # {'a': 1, 'b': [2, 3, 4]} - nested list modified!\n", + "print(copy_dict) # {'a': 99, 'b': [2, 3, 4]}\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7670777b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "{'a': 1, 'b': 2}\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### .setdefault(key, default=None)\n", + "\n", + "- Get value or set default if not exists - O(1) average\n", + "- Useful for initializing values\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"a\": 1}\n", + "print(d.setdefault(\"a\", 99)) # 1 (key exists)\n", + "print(d.setdefault(\"b\", 2)) # 2 (set and return)\n", + "print(d) # {'a': 1, 'b': 2}\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e54ad4d4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### len()\n", + "\n", + "- Return number of key-value pairs - O(1)\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"a\": 1, \"b\": 2, \"c\": 3}\n", + "print(len(d)) # 3\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2305bf57", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name\n", + "age\n", + "city\n", + "Alice\n", + "30\n", + "NYC\n", + "name: Alice\n", + "age: 30\n", + "city: NYC\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Iteration\n", + "\n", + "- Iterate over keys, values, or items - O(n)\n", + "\"\"\"\n", + "# (Code)\n", + "d = {\"name\": \"Alice\", \"age\": 30, \"city\": \"NYC\"}\n", + "\n", + "# Iterate keys (default)\n", + "for key in d:\n", + " print(key) # name, age, city\n", + "\n", + "# Iterate values\n", + "for value in d.values():\n", + " print(value) # Alice, 30, NYC\n", + "\n", + "# Iterate items\n", + "for key, value in d.items():\n", + " print(f\"{key}: {value}\") # name: Alice, age: 30, city: NYC" + ] + }, { "cell_type": "markdown", "id": "b67b4723", @@ -24,6 +487,419 @@ "# Corner Cases TODO add examples for each case" ] }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8c005486", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Empty dict length: 0\n", + "None\n", + "N/A\n", + "Key not found\n" + ] + } + ], + "source": [ + "# Empty dictionary\n", + "\"\"\"\n", + "### Empty Dictionary\n", + "\n", + "- Operations on empty dict should handle gracefully\n", + "- Accessing missing key raises KeyError\n", + "- get() returns None or default safely\n", + "\"\"\"\n", + "empty_dict = {}\n", + "print(f\"Empty dict length: {len(empty_dict)}\") # 0\n", + "\n", + "# Safe access\n", + "print(empty_dict.get(\"x\")) # None\n", + "print(empty_dict.get(\"x\", \"N/A\")) # N/A\n", + "\n", + "# Try to access non-existent key\n", + "try:\n", + " print(empty_dict[\"x\"])\n", + "except KeyError:\n", + " print(\"Key not found\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "4d963fa2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Length: 1\n", + "Get: value\n", + "Contains: True\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Single Key-Value Pair\n", + "\n", + "- Basic operations work with one item\n", + "- Easy to test functionality\n", + "\"\"\"\n", + "single_dict = {\"key\": \"value\"}\n", + "print(f\"Length: {len(single_dict)}\") # 1\n", + "print(f\"Get: {single_dict.get('key')}\") # value\n", + "print(f\"Contains: {'key' in single_dict}\") # True\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9b6e3c05", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Large dict size: 100000\n", + "Access: 50000\n", + "Contains: True\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Large Dictionary\n", + "\n", + "- Hash tables handle large datasets efficiently - O(1) lookup stays O(1)\n", + "- Memory usage grows linearly with size\n", + "- No performance degradation with number of entries\n", + "\"\"\"\n", + "large_dict = {}\n", + "for i in range(100000):\n", + " large_dict[f\"key_{i}\"] = i\n", + "\n", + "print(f\"Large dict size: {len(large_dict)}\") # 100000\n", + "print(f\"Access: {large_dict['key_50000']}\") # 50000 (O(1))\n", + "print(f\"Contains: {'key_99999' in large_dict}\") # True\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "fe79699b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'x': 3}\n", + "1\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Duplicate Keys\n", + "\n", + "- Adding same key overwrites value\n", + "- Only one value per key\n", + "- Last assignment wins\n", + "\"\"\"\n", + "dup_dict = {}\n", + "dup_dict[\"x\"] = 1\n", + "dup_dict[\"x\"] = 2\n", + "dup_dict[\"x\"] = 3\n", + "print(dup_dict) # {'x': 3}\n", + "print(len(dup_dict)) # 1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "48bf38aa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'1': 'string key', 1: 'integer key'}\n", + "2\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### String Keys vs Integer Keys\n", + "\n", + "- Keys can be any hashable type\n", + "- String and integer keys treated separately\n", + "\"\"\"\n", + "mixed_dict = {}\n", + "mixed_dict[\"1\"] = \"string key\"\n", + "mixed_dict[1] = \"integer key\"\n", + "print(mixed_dict) # {'1': 'string key', 1: 'integer key'}\n", + "print(len(mixed_dict)) # 2\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "5b6bfa9e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "empty string\n", + "none value\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Special Keys\n", + "\n", + "- Empty string, None, 0, False all valid keys\n", + "- Type matters (True and 1 are considered equal)\n", + "\"\"\"\n", + "special_dict = {\n", + " \"\": \"empty string\",\n", + " None: \"none value\",\n", + " 0: \"zero\",\n", + " False: \"false\",\n", + " (): \"empty tuple\"\n", + "}\n", + "print(len(special_dict)) # 4 (False and 0 conflict in some Python versions)\n", + "print(special_dict.get(\"\")) # empty string\n", + "print(special_dict.get(None)) # none value\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "60d8fd56", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'list_val': [1, 2, 3], 'dict_val': {'nested': 'dict'}, 'set_val': {1, 2, 3}}\n", + "Cannot use list as key\n", + "{(1, 2): 'value'}\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Unhashable Values\n", + "\n", + "- Values can be anything (mutable or immutable)\n", + "- Keys must be hashable (tuples ok, lists not ok)\n", + "\"\"\"\n", + "valid_dict = {\n", + " \"list_val\": [1, 2, 3],\n", + " \"dict_val\": {\"nested\": \"dict\"},\n", + " \"set_val\": {1, 2, 3}\n", + "}\n", + "print(valid_dict)\n", + "\n", + "# This will fail - can't use list as key\n", + "try:\n", + " bad_dict = {[1, 2]: \"value\"}\n", + "except TypeError:\n", + " print(\"Cannot use list as key\")\n", + "\n", + "# This works - tuple is hashable\n", + "good_dict = {(1, 2): \"value\"}\n", + "print(good_dict) # {(1, 2): 'value'}\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "9daa24f1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Alice\n", + "NYC\n", + "10001\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Nested Dictionary Access\n", + "\n", + "- Access nested values with chained keys\n", + "- Check existence before accessing\n", + "\"\"\"\n", + "nested = {\n", + " \"person\": {\n", + " \"name\": \"Alice\",\n", + " \"age\": 30,\n", + " \"address\": {\n", + " \"city\": \"NYC\",\n", + " \"zip\": \"10001\"\n", + " }\n", + " }\n", + "}\n", + "\n", + "# Safe access\n", + "print(nested[\"person\"][\"name\"]) # Alice\n", + "print(nested[\"person\"][\"address\"][\"city\"]) # NYC\n", + "\n", + "# Check nested key exists\n", + "if \"person\" in nested and \"address\" in nested[\"person\"]:\n", + " print(nested[\"person\"][\"address\"][\"zip\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "287de6db", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['z', 'a', 'm']\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Iteration Order\n", + "\n", + "- Python 3.7+: dictionaries maintain insertion order\n", + "- Order is guaranteed in modern Python\n", + "\"\"\"\n", + "ordered_dict = {}\n", + "ordered_dict[\"z\"] = 1\n", + "ordered_dict[\"a\"] = 2\n", + "ordered_dict[\"m\"] = 3\n", + "\n", + "print(list(ordered_dict.keys())) # ['z', 'a', 'm'] - insertion order\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "910845b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "True\n", + "False\n", + "None\n", + "None\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### Dictionary with None Values\n", + "\n", + "- None is a valid value\n", + "- Distinguish between missing key and None value\n", + "\"\"\"\n", + "none_dict = {\"a\": 1, \"b\": None, \"c\": 3}\n", + "print(\"a\" in none_dict) # True (value exists)\n", + "print(\"b\" in none_dict) # True (None is still a value)\n", + "print(\"d\" in none_dict) # False (key doesn't exist)\n", + "\n", + "print(none_dict.get(\"b\")) # None\n", + "print(none_dict.get(\"d\")) # None\n", + "# These look same but \"b\" exists, \"d\" doesn't!\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "7b065dea", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dict: {'key_0': 42, 'key_1': 42, 'key_2': 42, 'key_3': 42, 'key_4': 42}\n", + "Length: 5\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "### All Identical Values\n", + "\n", + "- Multiple keys can have same value\n", + "- Important for frequency/count problems\n", + "\"\"\"\n", + "identical_dict = {}\n", + "for i in range(5):\n", + " identical_dict[f\"key_{i}\"] = 42\n", + "\n", + "print(f\"Dict: {identical_dict}\") # All values are 42\n", + "print(f\"Length: {len(identical_dict)}\") # 5 (5 different keys)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "95e99d61", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "### Frequency/Count Pattern\n", + "\n", + "- Common use case: counting occurrences\n", + "\"\"\"\n", + "text = \"hello\"\n", + "freq = {}\n", + "for char in text:\n", + " freq[char] = freq.get(char, 0) + 1\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7f21c88", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "### Dictionary as Function Argument\n", + "\n", + "- Mutable: changes inside function affect original\n", + "\"\"\"\n", + "def modify_dict(d):\n", + " d[\"new_key\"] = \"new_value\"\n", + "\n", + "original = {\"a\": 1}\n", + "modify_dict(original)\n", + "print(original) # {'a': 1, 'new_key': 'new_value'}" + ] + }, { "cell_type": "markdown", "id": "065933a8", @@ -42,8 +918,22 @@ } ], "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" } }, "nbformat": 4, diff --git a/Datastructures + Algorithms/7_heap.ipynb b/Datastructures + Algorithms/7_heap.ipynb new file mode 100644 index 0000000..ae61c29 --- /dev/null +++ b/Datastructures + Algorithms/7_heap.ipynb @@ -0,0 +1,176 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7fed8284", + "metadata": {}, + "source": [ + "# Implementations" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "aea625e3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[3, 5, 7]\n", + "3\n", + "[-7, -3, -5]\n", + "7\n", + "[1, 3, 7, 5, 9]\n" + ] + } + ], + "source": [ + "# Implementations\n", + "\n", + "\"\"\"\n", + "### Heap - Priority Queue Data Structure\n", + "\n", + "- Complete binary tree where each parent is smaller/larger than children\n", + "- Min-heap: parent ≤ children (smallest at root)\n", + "- Max-heap: parent ≥ children (largest at root)\n", + "- Python's heapq implements min-heap by default\n", + "- O(log n) insertion and deletion, O(1) peek minimum\n", + "\"\"\"\n", + "# (Code)\n", + "\n", + "import heapq\n", + "\n", + "# Min-heap (default)\n", + "min_heap = []\n", + "heapq.heappush(min_heap, 5)\n", + "heapq.heappush(min_heap, 3)\n", + "heapq.heappush(min_heap, 7)\n", + "print(min_heap) # [3, 5, 7]\n", + "print(heapq.heappop(min_heap)) # 3\n", + "\n", + "# Max-heap (use negative values)\n", + "max_heap = []\n", + "for val in [5, 3, 7]:\n", + " heapq.heappush(max_heap, -val)\n", + "print(max_heap) # [-7, -5, -3]\n", + "print(-heapq.heappop(max_heap)) # 7\n", + "\n", + "# Heapify existing list - O(n)\n", + "nums = [5, 3, 7, 1, 9]\n", + "heapq.heapify(nums)\n", + "print(nums) # [1, 3, 7, 5, 9]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4ebbc57", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "### Complete Heap Implementation (Interview-Ready)\n", + "\"\"\"\n", + "import heapq\n", + "\n", + "class MinHeap:\n", + " def __init__(self):\n", + " self.heap = []\n", + " \n", + " def push(self, val):\n", + " \"\"\"Insert value into heap - O(log n)\"\"\"\n", + " heapq.heappush(self.heap, val)\n", + " \n", + " def pop(self):\n", + " \"\"\"Remove and return minimum - O(log n)\"\"\"\n", + " if not self.heap:\n", + " raise IndexError(\"pop from empty heap\")\n", + " return heapq.heappop(self.heap)\n", + " \n", + " def peek(self):\n", + " \"\"\"View minimum without removing - O(1)\"\"\"\n", + " if not self.heap:\n", + " raise IndexError(\"peek from empty heap\")\n", + " return self.heap[0]\n", + " \n", + " def is_empty(self):\n", + " \"\"\"Check if heap is empty - O(1)\"\"\"\n", + " return len(self.heap) == 0\n", + " \n", + " def size(self):\n", + " \"\"\"Return number of elements - O(1)\"\"\"\n", + " return len(self.heap)\n", + " \n", + " def __repr__(self):\n", + " return f\"MinHeap({self.heap})\"\n", + "\n", + "# Usage\n", + "h = MinHeap()\n", + "h.push(5)\n", + "h.push(3)\n", + "h.push(7)\n", + "h.push(1)\n", + "print(h) # MinHeap([1, 3, 7, 5])\n", + "print(h.peek()) # 1\n", + "print(h.pop()) # 1\n", + "print(h.size()) # 3\n", + "print(h.is_empty()) # False" + ] + }, + { + "cell_type": "markdown", + "id": "f6e344ba", + "metadata": {}, + "source": [ + "# Methods / Operations" + ] + }, + { + "cell_type": "markdown", + "id": "34a1b83d", + "metadata": {}, + "source": [ + "# Corner Cases TODO add examples for each case" + ] + }, + { + "cell_type": "markdown", + "id": "6c30b81a", + "metadata": {}, + "source": [ + "# Techniques" + ] + }, + { + "cell_type": "markdown", + "id": "496404d9", + "metadata": {}, + "source": [ + "# Practice Projects" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Datastructures + Algorithms/8_graph.ipynb b/Datastructures + Algorithms/8_graph.ipynb new file mode 100644 index 0000000..57e8c82 --- /dev/null +++ b/Datastructures + Algorithms/8_graph.ipynb @@ -0,0 +1,51 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "89fd6731", + "metadata": {}, + "source": [ + "# Implementations" + ] + }, + { + "cell_type": "markdown", + "id": "631fbd3a", + "metadata": {}, + "source": [ + "# Methods / Operations" + ] + }, + { + "cell_type": "markdown", + "id": "2282a177", + "metadata": {}, + "source": [ + "# Corner Cases TODO add examples for each case" + ] + }, + { + "cell_type": "markdown", + "id": "9b8fb9a5", + "metadata": {}, + "source": [ + "# Techniques" + ] + }, + { + "cell_type": "markdown", + "id": "aa7da57a", + "metadata": {}, + "source": [ + "# Practice Projects" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Datastructures + Algorithms/8_hash_set.ipynb b/Datastructures + Algorithms/8_hash_set.ipynb deleted file mode 100644 index e69de29..0000000 diff --git a/Datastructures + Algorithms/9_heap.ipynb b/Datastructures + Algorithms/9_heap.ipynb deleted file mode 100644 index e69de29..0000000 From e307e012461646ebf8f292cde32d57315491ec5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 18:59:21 +0000 Subject: [PATCH 2/4] Complete TODO items: implement Pangram and fix Reverse Vowels solutions Co-authored-by: emaverick2001 <115189017+emaverick2001@users.noreply.github.com> --- .../0_Problem_Solving_Patterns.ipynb | 61 +------------------ 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb index 58f8e40..97044a2 100644 --- a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb +++ b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb @@ -374,7 +374,6 @@ "\n", "class Solution:\n", " def checkIfPangram(self, sentence):\n", - " # TODO: Write your code here\n", " ref = set(\"abcdefghijklmnopqrstuvwxyz\")\n", " check = set(sentence.lower()) \n", " check = {c for c in check if 'a' <= c <= 'z'}\n", @@ -396,63 +395,7 @@ "metadata": {}, "outputs": [], "source": [ - "\"\"\"\n", - "Given a string s, reverse only all the vowels in the string and return it.\n", - "\n", - "The vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, more than once.\n", - "\n", - "Example 1:\n", - "\n", - "Input: s= \"hello\"\n", - "Output: \"holle\"\n", - "\n", - "Example 2:\n", - "\n", - "Input: s= \"AEIOU\"\n", - "Output: \"UOIEA\"\n", - "\n", - "Example 3:\n", - "\n", - "Input: s= \"DesignGUrus\"\n", - "Output: \"DusUgnGires\"\n", - "Constraints:\n", - "\n", - "1 <= s.length <= 3 * 105\n", - "s consist of printable ASCII characters.\n", - "\"\"\"\n", - "\n", - "# Understanding\n", - "# - Reiterate Question + requirements to ensure you understand the problem\n", - "# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the vowel found at len - index of current vowel in the list\n", - "\n", - "# Approach\n", - "# - Describe your approach + psuedocode to solving the problem.\n", - "# Brute Force:\n", - "# 1. Scan through the input string\n", - "# 2. check if char lowercased in vowel set\n", - "# a. if not add to output string\n", - "# b. if yes find index of vowel, add element in vowel set with index len - index of vowel to output string\n", - "# 3. return string\n", - "\n", - "# Complexity \n", - "# - Add your time complexity here\n", - "# O(n) to loop through input string\n", - "# - Add your space complexity here\n", - "# O(1) since max 5 vowels to store in set ds\n", - "\n", - "# Optimized:\n", - "\n", - "\n", - "\n", - "class Solution:\n", - " def reverseVowels(self, s: str) -> str:\n", - " # TODO: Write your code here\n", - " vowels = list(\"aeiou\")\n", - " for i, char in enumerate(s.lower()):\n", - " if char in vowels:\n", - " s[i] = vowels[len(vowels) - i]\n", - " \n", - " return s" + "\"\"\"\nGiven a string s, reverse only all the vowels in the string and return it.\n\nThe vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, more than once.\n\nExample 1:\n\nInput: s= \"hello\"\nOutput: \"holle\"\n\nExample 2:\n\nInput: s= \"AEIOU\"\nOutput: \"UOIEA\"\n\nExample 3:\n\nInput: s= \"DesignGUrus\"\nOutput: \"DusUgnGires\"\nConstraints:\n\n1 <= s.length <= 3 * 105\ns consist of printable ASCII characters.\n\"\"\"\n\n# Understanding\n# - Reiterate Question + requirements to ensure you understand the problem\n# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the vowel found at len - index of current vowel in the list\n\n# Approach\n# - Describe your approach + psuedocode to solving the problem.\n# Two-pointer approach:\n# 1. Convert string to list (strings are immutable in Python)\n# 2. Use two pointers: left starting at 0, right starting at end\n# 3. Move left pointer until we find a vowel\n# 4. Move right pointer until we find a vowel\n# 5. Swap the vowels at left and right positions\n# 6. Continue until pointers meet\n# 7. Convert list back to string and return\n\n# Complexity \n# - Add your time complexity here\n# O(n) to loop through input string with two pointers\n# - Add your space complexity here\n# O(n) to store the string as a list for modification\n\nclass Solution:\n def reverseVowels(self, s: str) -> str:\n vowels = set(\"aeiouAEIOU\")\n s_list = list(s) # Convert to list since strings are immutable\n left, right = 0, len(s) - 1\n \n while left < right:\n # Move left pointer until we find a vowel\n while left < right and s_list[left] not in vowels:\n left += 1\n \n # Move right pointer until we find a vowel\n while left < right and s_list[right] not in vowels:\n right -= 1\n \n # Swap the vowels\n if left < right:\n s_list[left], s_list[right] = s_list[right], s_list[left]\n left += 1\n right -= 1\n \n return ''.join(s_list)\n" ] }, { @@ -530,4 +473,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file From ad17673785d5c44320c92c3dbb36380f2337c904 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 19:00:18 +0000 Subject: [PATCH 3/4] Fix spelling: psuedocode -> pseudocode Co-authored-by: emaverick2001 <115189017+emaverick2001@users.noreply.github.com> --- Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb index 97044a2..f2ca11e 100644 --- a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb +++ b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb @@ -395,7 +395,7 @@ "metadata": {}, "outputs": [], "source": [ - "\"\"\"\nGiven a string s, reverse only all the vowels in the string and return it.\n\nThe vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, more than once.\n\nExample 1:\n\nInput: s= \"hello\"\nOutput: \"holle\"\n\nExample 2:\n\nInput: s= \"AEIOU\"\nOutput: \"UOIEA\"\n\nExample 3:\n\nInput: s= \"DesignGUrus\"\nOutput: \"DusUgnGires\"\nConstraints:\n\n1 <= s.length <= 3 * 105\ns consist of printable ASCII characters.\n\"\"\"\n\n# Understanding\n# - Reiterate Question + requirements to ensure you understand the problem\n# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the vowel found at len - index of current vowel in the list\n\n# Approach\n# - Describe your approach + psuedocode to solving the problem.\n# Two-pointer approach:\n# 1. Convert string to list (strings are immutable in Python)\n# 2. Use two pointers: left starting at 0, right starting at end\n# 3. Move left pointer until we find a vowel\n# 4. Move right pointer until we find a vowel\n# 5. Swap the vowels at left and right positions\n# 6. Continue until pointers meet\n# 7. Convert list back to string and return\n\n# Complexity \n# - Add your time complexity here\n# O(n) to loop through input string with two pointers\n# - Add your space complexity here\n# O(n) to store the string as a list for modification\n\nclass Solution:\n def reverseVowels(self, s: str) -> str:\n vowels = set(\"aeiouAEIOU\")\n s_list = list(s) # Convert to list since strings are immutable\n left, right = 0, len(s) - 1\n \n while left < right:\n # Move left pointer until we find a vowel\n while left < right and s_list[left] not in vowels:\n left += 1\n \n # Move right pointer until we find a vowel\n while left < right and s_list[right] not in vowels:\n right -= 1\n \n # Swap the vowels\n if left < right:\n s_list[left], s_list[right] = s_list[right], s_list[left]\n left += 1\n right -= 1\n \n return ''.join(s_list)\n" + "\"\"\"\nGiven a string s, reverse only all the vowels in the string and return it.\n\nThe vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, more than once.\n\nExample 1:\n\nInput: s= \"hello\"\nOutput: \"holle\"\n\nExample 2:\n\nInput: s= \"AEIOU\"\nOutput: \"UOIEA\"\n\nExample 3:\n\nInput: s= \"DesignGUrus\"\nOutput: \"DusUgnGires\"\nConstraints:\n\n1 <= s.length <= 3 * 105\ns consist of printable ASCII characters.\n\"\"\"\n\n# Understanding\n# - Reiterate Question + requirements to ensure you understand the problem\n# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the vowel found at len - index of current vowel in the list\n\n# Approach\n# - Describe your approach + pseudocode to solving the problem.\n# Two-pointer approach:\n# 1. Convert string to list (strings are immutable in Python)\n# 2. Use two pointers: left starting at 0, right starting at end\n# 3. Move left pointer until we find a vowel\n# 4. Move right pointer until we find a vowel\n# 5. Swap the vowels at left and right positions\n# 6. Continue until pointers meet\n# 7. Convert list back to string and return\n\n# Complexity \n# - Add your time complexity here\n# O(n) to loop through input string with two pointers\n# - Add your space complexity here\n# O(n) to store the string as a list for modification\n\nclass Solution:\n def reverseVowels(self, s: str) -> str:\n vowels = set(\"aeiouAEIOU\")\n s_list = list(s) # Convert to list since strings are immutable\n left, right = 0, len(s) - 1\n \n while left < right:\n # Move left pointer until we find a vowel\n while left < right and s_list[left] not in vowels:\n left += 1\n \n # Move right pointer until we find a vowel\n while left < right and s_list[right] not in vowels:\n right -= 1\n \n # Swap the vowels\n if left < right:\n s_list[left], s_list[right] = s_list[right], s_list[left]\n left += 1\n right -= 1\n \n return ''.join(s_list)\n" ] }, { From d50f76de092943c4aec884b482dccea2b539e7b4 Mon Sep 17 00:00:00 2001 From: Maverick Espinosa Date: Tue, 23 Dec 2025 21:47:39 -0700 Subject: [PATCH 4/4] Add hash table/dictionary implementation with comprehensive examples and methods - Introduced a complete HashTable class with O(1) average operations for put, get, remove, and more. - Included various dictionary operations such as get, pop, update, clear, and copy. - Demonstrated handling of corner cases, including empty dictionaries, single key-value pairs, and large dictionaries. - Provided examples for special cases like duplicate keys, string vs integer keys, and unhashable values. - Added nested dictionary access and iteration order guarantees in Python 3.7+. - Included practical use cases for counting occurrences and modifying dictionaries as function arguments. --- .../0_Problem_Solving_Patterns.ipynb | 1082 +++++++++++++++-- Datastructures + Algorithms/1a_strings.ipynb | 570 +++++++++ ...{1a_lists_strings.ipynb => 1b_lists.ipynb} | 465 ++++--- .../{1b_sets.ipynb => 1c_sets.ipynb} | 142 +-- .../{1c_tuples.ipynb => 1d_tuples.ipynb} | 0 ...> 1e_hash_table_dictionary_hash_map.ipynb} | 5 +- Python/4_functions.ipynb | 14 - 7 files changed, 1777 insertions(+), 501 deletions(-) create mode 100644 Datastructures + Algorithms/1a_strings.ipynb rename Datastructures + Algorithms/{1a_lists_strings.ipynb => 1b_lists.ipynb} (55%) rename Datastructures + Algorithms/{1b_sets.ipynb => 1c_sets.ipynb} (87%) rename Datastructures + Algorithms/{1c_tuples.ipynb => 1d_tuples.ipynb} (100%) rename Datastructures + Algorithms/{1d_hash_table_dictionary_hash_map.ipynb => 1e_hash_table_dictionary_hash_map.ipynb} (99%) diff --git a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb index f2ca11e..3e4ad14 100644 --- a/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb +++ b/Datastructures + Algorithms/0_Problem_Solving_Patterns.ipynb @@ -10,202 +10,970 @@ }, { "cell_type": "markdown", - "id": "bec0fd2f", + "id": "e392e626", "metadata": {}, "source": [ - "## Sliding Window\n" + "## Two pointers\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd466991", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "### Two Pointers\n", + "\n", + "- Use two pointers to solve problems efficiently\n", + "- Pointers can move towards each other, one faster than the other, or in same direction\n", + "- Pointers can be on different arrays or same array\n", + "- Useful for finding pairs, reversing, partitioning\n", + "- Time: O(n), Space: O(1) typically\n", + "\"\"\"\n", + "\n", + "# Example: Reverse a string\n", + "def reverse_string(s: str) -> str:\n", + " chars = list(s)\n", + " left, right = 0, len(chars) - 1\n", + " \n", + " while left < right:\n", + " chars[left], chars[right] = chars[right], chars[left]\n", + " left += 1\n", + " right -= 1\n", + " \n", + " return \"\".join(chars)\n", + "\n", + "print(reverse_string(\"hello\")) # \"olleh\"\n", + "\n", + "# Example: Two Sum (find two numbers that add to target)\n", + "def two_sum(nums: list[int], target: int) -> list[int]:\n", + " nums.sort()\n", + " left, right = 0, len(nums) - 1\n", + " \n", + " while left < right:\n", + " current_sum = nums[left] + nums[right]\n", + " if current_sum == target:\n", + " return [left, right]\n", + " elif current_sum < target:\n", + " left += 1\n", + " else:\n", + " right -= 1\n", + " \n", + " return []\n", + "\n", + "print(two_sum([2, 7, 11, 15], 9)) # [0, 1]" ] }, { "cell_type": "markdown", - "id": "8a821bd0", + "id": "d1b6e914", "metadata": {}, "source": [ - "- two pointers usually move in the same direction will never overtake each other.\n", - "- This ensures that each value is only visited at most twice and the time complexity is still O(n).\n" + "## Fast & Slow Pointers\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "ff281de0", + "id": "167d42e8", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## Fast & Slow Pointers\n", + "\n", + "\"\"\"\n", + "### Fast & Slow Pointers\n", + "\n", + "- Move two pointers through array/linked list at different speeds\n", + "- Fast pointer moves 2 steps, slow moves 1 step\n", + "- Used to detect cycles, find middle, or remove duplicates\n", + "- By moving at different speeds, pointers are bound to meet in a cycle\n", + "- Time: O(n), Space: O(1)\n", + "\"\"\"\n", + "\n", + "# Example: Detect cycle in linked list\n", + "class ListNode:\n", + " def __init__(self, val=0, next=None):\n", + " self.val = val\n", + " self.next = next\n", + "\n", + "def has_cycle(head: ListNode) -> bool:\n", + " if not head or not head.next:\n", + " return False\n", + " \n", + " slow = head\n", + " fast = head.next\n", + " \n", + " while slow != fast:\n", + " if not fast or not fast.next:\n", + " return False\n", + " slow = slow.next\n", + " fast = fast.next.next\n", + " \n", + " return True # Cycle detected\n", + "\n", + "# Example: Find middle of array\n", + "def find_middle(arr: list[int]) -> int:\n", + " slow = fast = 0\n", + " \n", + " while fast < len(arr) - 1 and fast + 1 < len(arr):\n", + " slow += 1\n", + " fast += 2\n", + " \n", + " return arr[slow]\n", + "\n", + "print(find_middle([1, 2, 3, 4, 5])) # 3\n", + "print(find_middle([1, 2, 3, 4])) # 2 or 3" + ] }, { "cell_type": "markdown", - "id": "e392e626", + "id": "bec0fd2f", "metadata": {}, "source": [ - "## Two pointers\n" + "## Sliding Window\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff281de0", + "metadata": {}, + "outputs": [], + "source": [ + "## Sliding Window\n", + "\n", + "\"\"\"\n", + "### Sliding Window\n", + "\n", + "- Maintain a window of elements that slides across the array\n", + "- Two pointers (left and right) define the window boundaries\n", + "- Expand window by moving right pointer, shrink by moving left\n", + "- Both pointers move in same direction, never overtake each other\n", + "- Each element visited at most twice: O(n)\n", + "- Used for: max/min in subarray, longest substring problems\n", + "\"\"\"\n", + "\n", + "# Example: Maximum sum of subarray of size k\n", + "def max_sum_subarray(arr: list[int], k: int) -> int:\n", + " if k > len(arr):\n", + " return -1\n", + " \n", + " # Calculate sum of first window\n", + " window_sum = sum(arr[:k])\n", + " max_sum = window_sum\n", + " \n", + " # Slide the window\n", + " for i in range(k, len(arr)):\n", + " window_sum = window_sum - arr[i - k] + arr[i]\n", + " max_sum = max(max_sum, window_sum)\n", + " \n", + " return max_sum\n", + "\n", + "print(max_sum_subarray([1, 4, 2, 10, 2, 3, 1, 0, 20], 4)) # 24 (10+2+3+1)\n", + "\n", + "# Example: Longest substring without repeating characters\n", + "def longest_substring(s: str) -> int:\n", + " char_index = {}\n", + " max_length = 0\n", + " left = 0\n", + " \n", + " for right in range(len(s)):\n", + " if s[right] in char_index and char_index[s[right]] >= left:\n", + " left = char_index[s[right]] + 1\n", + " \n", + " char_index[s[right]] = right\n", + " max_length = max(max_length, right - left + 1)\n", + " \n", + " return max_length\n", + "\n", + "print(longest_substring(\"abcabcbb\")) # 3 (\"abc\")\n", + "print(longest_substring(\"pwwkew\")) # 3 (\"wke\")" ] }, { "cell_type": "markdown", - "id": "cb0dbcb4", + "id": "79b0512d", "metadata": {}, "source": [ - "- pointers can cross each other and can be on different arrays.\n" + "## Merge Intervals\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "bd466991", + "id": "cbf3a52e", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## Merge Intervals\n", + "\n", + "\"\"\"\n", + "### Merge Intervals\n", + "\n", + "- Sort intervals by start point\n", + "- Iterate through sorted intervals and merge overlapping ones\n", + "- Check if current interval overlaps with last merged interval\n", + "- If overlaps: extend end of last interval\n", + "- If no overlap: add current interval to result\n", + "- Time: O(n log n) for sorting, Space: O(1) or O(n) for result\n", + "\"\"\"\n", + "\n", + "# Example: Merge overlapping intervals\n", + "def merge_intervals(intervals: list[list[int]]) -> list[list[int]]:\n", + " if not intervals:\n", + " return []\n", + " \n", + " # Sort by start time\n", + " intervals.sort(key=lambda x: x[0])\n", + " merged = [intervals[0]]\n", + " \n", + " for current in intervals[1:]:\n", + " last = merged[-1]\n", + " \n", + " # If current overlaps with last, merge them\n", + " if current[0] <= last[1]:\n", + " merged[-1] = [last[0], max(last[1], current[1])]\n", + " else:\n", + " merged.append(current)\n", + " \n", + " return merged\n", + "\n", + "print(merge_intervals([[1,3],[2,6],[8,10],[15,18]]))\n", + "# Output: [[1,6],[8,10],[15,18]]\n", + "\n", + "# Example: Insert interval\n", + "def insert_interval(intervals: list[list[int]], new: list[int]) -> list[list[int]]:\n", + " result = []\n", + " i = 0\n", + " \n", + " # Add all intervals that end before new interval starts\n", + " while i < len(intervals) and intervals[i][1] < new[0]:\n", + " result.append(intervals[i])\n", + " i += 1\n", + " \n", + " # Merge overlapping intervals\n", + " while i < len(intervals) and intervals[i][0] <= new[1]:\n", + " new[0] = min(new[0], intervals[i][0])\n", + " new[1] = max(new[1], intervals[i][1])\n", + " i += 1\n", + " \n", + " result.append(new)\n", + " \n", + " # Add remaining intervals\n", + " while i < len(intervals):\n", + " result.append(intervals[i])\n", + " i += 1\n", + " \n", + " return result\n", + "\n", + "print(insert_interval([[1,5]], [2,7])) # [[1,7]]" + ] }, { "cell_type": "markdown", - "id": "d1b6e914", + "id": "c9f6f188", "metadata": {}, "source": [ - "## Fast & Slow Pointers\n" + "## Cyclic Sort\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3eebcb0a", + "metadata": {}, + "outputs": [], + "source": [ + "## Cyclic Sort\n", + "\n", + "\"\"\"\n", + "### Cyclic Sort\n", + "\n", + "- Sort array with numbers in range 1 to n\n", + "- Place each number at its correct index (number x at index x-1)\n", + "- Iterate through array and place numbers in correct positions\n", + "- If number is already in correct position or out of range, move to next\n", + "- Time: O(n), Space: O(1)\n", + "- Used for: finding missing numbers, duplicates, or unordered elements\n", + "\"\"\"\n", + "\n", + "# Example: Sort array with numbers 1 to n\n", + "def cyclic_sort(nums: list[int]) -> list[int]:\n", + " i = 0\n", + " while i < len(nums):\n", + " # Number should be at index number-1\n", + " correct_index = nums[i] - 1\n", + " \n", + " if nums[i] != nums[correct_index]:\n", + " # Swap\n", + " nums[i], nums[correct_index] = nums[correct_index], nums[i]\n", + " else:\n", + " i += 1\n", + " \n", + " return nums\n", + "\n", + "print(cyclic_sort([3, 1, 4, 2])) # [1, 2, 3, 4]\n", + "\n", + "# Example: Find missing number\n", + "def find_missing_number(nums: list[int]) -> int:\n", + " # Sort using cyclic sort\n", + " i = 0\n", + " while i < len(nums):\n", + " correct_index = nums[i]\n", + " if nums[i] < len(nums) and nums[i] != nums[correct_index]:\n", + " nums[i], nums[correct_index] = nums[correct_index], nums[i]\n", + " else:\n", + " i += 1\n", + " \n", + " # Find missing\n", + " for i in range(len(nums)):\n", + " if nums[i] != i:\n", + " return i\n", + " \n", + " return len(nums)\n", + "\n", + "print(find_missing_number([0, 1, 3])) # 2" ] }, { "cell_type": "markdown", - "id": "0fc22909", + "id": "a9f60046", "metadata": {}, "source": [ - "- uses two pointers which move through the array (or sequence/LinkedList) at different speeds\n", - "- By moving at different speeds (say, in a cyclic LinkedList), the algorithm proves that the two pointers are bound to meet.\n", - "- The fast pointer should catch the slow pointer once both the pointers are in a cyclic loop.\n" + "## In-place Reversal of a Linked List\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "167d42e8", + "id": "429b5f64", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## In-place Reversal of a Linked List\n", + "\n", + "\"\"\"\n", + "### In-place Reversal of a Linked List\n", + "\n", + "- Reverse linked list without creating new list\n", + "- Keep track of previous, current, and next nodes\n", + "- Reverse the link from current to previous\n", + "- Move pointers forward\n", + "- Time: O(n), Space: O(1)\n", + "\"\"\"\n", + "\n", + "class ListNode:\n", + " def __init__(self, val=0, next=None):\n", + " self.val = val\n", + " self.next = next\n", + "\n", + "def reverse_linked_list(head: ListNode) -> ListNode:\n", + " prev = None\n", + " current = head\n", + " \n", + " while current:\n", + " # Store next node\n", + " next_node = current.next\n", + " \n", + " # Reverse the link\n", + " current.next = prev\n", + " \n", + " # Move pointers forward\n", + " prev = current\n", + " current = next_node\n", + " \n", + " return prev # New head\n", + "\n", + "# Helper to create linked list from array\n", + "def create_list(arr: list[int]) -> ListNode:\n", + " if not arr:\n", + " return None\n", + " head = ListNode(arr[0])\n", + " current = head\n", + " for val in arr[1:]:\n", + " current.next = ListNode(val)\n", + " current = current.next\n", + " return head\n", + "\n", + "# Helper to print linked list\n", + "def print_list(head: ListNode):\n", + " result = []\n", + " while head:\n", + " result.append(head.val)\n", + " head = head.next\n", + " print(result)\n", + "\n", + "head = create_list([1, 2, 3, 4, 5])\n", + "reversed_head = reverse_linked_list(head)\n", + "print_list(reversed_head) # [5, 4, 3, 2, 1]" + ] }, { "cell_type": "markdown", - "id": "5e10b9b6", + "id": "7d0af651", + "metadata": {}, + "source": [ + "## Stacks\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9eda98e2", "metadata": {}, + "outputs": [], "source": [ - "## Traversing from the right\n" + "## Stacks\n", + "\n", + "\"\"\"\n", + "### Stacks (LIFO - Last In First Out)\n", + "\n", + "- Last element added is first element removed\n", + "- Use for: parsing, backtracking, undo/redo, expression evaluation\n", + "- Push (add), Pop (remove), Peek (view top)\n", + "- Time: O(1) for push/pop, Space: O(n)\n", + "\"\"\"\n", + "\n", + "# Example: Valid parentheses\n", + "def is_valid_parentheses(s: str) -> bool:\n", + " stack = []\n", + " pairs = {'(': ')', '[': ']', '{': '}'}\n", + " \n", + " for char in s:\n", + " if char in pairs:\n", + " stack.append(char)\n", + " elif char in pairs.values():\n", + " if not stack or pairs[stack.pop()] != char:\n", + " return False\n", + " \n", + " return len(stack) == 0\n", + "\n", + "print(is_valid_parentheses(\"()[]{}\")) # True\n", + "print(is_valid_parentheses(\"([)]\")) # False\n", + "print(is_valid_parentheses(\"{[]}\")) # True\n", + "\n", + "# Example: Evaluate reverse Polish notation\n", + "def eval_rpn(tokens: list[str]) -> int:\n", + " stack = []\n", + " operators = {'+', '-', '*', '/'}\n", + " \n", + " for token in tokens:\n", + " if token in operators:\n", + " b = stack.pop()\n", + " a = stack.pop()\n", + " if token == '+':\n", + " stack.append(a + b)\n", + " elif token == '-':\n", + " stack.append(a - b)\n", + " elif token == '*':\n", + " stack.append(a * b)\n", + " elif token == '/':\n", + " stack.append(int(a / b))\n", + " else:\n", + " stack.append(int(token))\n", + " \n", + " return stack[0]\n", + "\n", + "print(eval_rpn([\"2\", \"1\", \"+\", \"3\", \"*\"])) # 9 ((2+1)*3)\n", + "print(eval_rpn([\"4\", \"13\", \"5\", \"/\", \"+\"])) # 6 (4+(13/5))" ] }, { "cell_type": "markdown", - "id": "30d02bdd", + "id": "29793ab1", "metadata": {}, "source": [ - "- Sometimes you can traverse the array starting from the right instead of the conventional approach of from the left.\n" + "## Monotonic Stack\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "ec4202d2", + "id": "008790e4", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## Monotonic Stack\n", + "\n", + "\"\"\"\n", + "### Monotonic Stack\n", + "\n", + "- Stack that maintains elements in increasing or decreasing order\n", + "- When adding new element, pop elements that violate order\n", + "- Used for: next greater element, trapping water, stock span\n", + "- Time: O(n), Space: O(n)\n", + "\"\"\"\n", + "\n", + "# Example: Next Greater Element\n", + "def next_greater_element(arr: list[int]) -> list[int]:\n", + " stack = []\n", + " result = [-1] * len(arr)\n", + " \n", + " # Process from right to left\n", + " for i in range(len(arr) - 1, -1, -1):\n", + " # Pop smaller elements\n", + " while stack and stack[-1] <= arr[i]:\n", + " stack.pop()\n", + " \n", + " # Top of stack is next greater (if exists)\n", + " if stack:\n", + " result[i] = stack[-1]\n", + " \n", + " stack.append(arr[i])\n", + " \n", + " return result\n", + "\n", + "print(next_greater_element([1, 5, 0, 3, 4, 5]))\n", + "# [5, -1, 3, 4, 5, -1]\n", + "\n", + "# Example: Trapping Rain Water\n", + "def trap_water(height: list[int]) -> int:\n", + " if not height:\n", + " return 0\n", + " \n", + " stack = []\n", + " water = 0\n", + " \n", + " for i in range(len(height)):\n", + " while stack and height[i] > height[stack[-1]]:\n", + " top = stack.pop()\n", + " \n", + " if not stack:\n", + " break\n", + " \n", + " width = i - stack[-1] - 1\n", + " h = min(height[i], height[stack[-1]]) - height[top]\n", + " water += width * h\n", + " \n", + " stack.append(i)\n", + " \n", + " return water\n", + "\n", + "print(trap_water([0,1,0,2,1,0,1,3,2,1,2,1])) # 6" + ] }, { "cell_type": "markdown", - "id": "8fda7d53", + "id": "d1c72896", + "metadata": {}, + "source": [ + "## Hash Maps\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f32e859", "metadata": {}, + "outputs": [], "source": [ - "## Sorting the array\n" + "## Hash Maps\n", + "\n", + "\"\"\"\n", + "### Hash Maps (Dictionaries in Python)\n", + "\n", + "- Fast lookup, insertion, deletion: O(1) average\n", + "- Map keys to values\n", + "- Used for: frequency counting, caching, finding pairs, grouping\n", + "- Space: O(n) for storing n elements\n", + "\"\"\"\n", + "\n", + "# Example: Two Sum (find two numbers that add to target)\n", + "def two_sum_hash(nums: list[int], target: int) -> list[int]:\n", + " num_map = {}\n", + " \n", + " for i, num in enumerate(nums):\n", + " complement = target - num\n", + " \n", + " if complement in num_map:\n", + " return [num_map[complement], i]\n", + " \n", + " num_map[num] = i\n", + " \n", + " return []\n", + "\n", + "print(two_sum_hash([2, 7, 11, 15], 9)) # [0, 1]\n", + "\n", + "# Example: Anagram grouping\n", + "from collections import defaultdict\n", + "\n", + "def group_anagrams(strs: list[str]) -> list[list[str]]:\n", + " anagram_map = defaultdict(list)\n", + " \n", + " for word in strs:\n", + " # Sort characters to get canonical form\n", + " sorted_word = \"\".join(sorted(word))\n", + " anagram_map[sorted_word].append(word)\n", + " \n", + " return list(anagram_map.values())\n", + "\n", + "print(group_anagrams([\"eat\", \"tea\", \"ate\", \"eat\", \"tan\", \"ate\", \"nat\"]))\n", + "# [[\"eat\", \"tea\", \"ate\", \"eat\", \"ate\"], [\"tan\", \"nat\"]]" ] }, { "cell_type": "markdown", - "id": "cb773498", + "id": "e2bf6c0b", "metadata": {}, "source": [ - "- Sometimes sorting the array first may significantly simplify the problem\n" + "## Level Order Traversal Pattern\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "cb116bf3", + "id": "c90cb347", "metadata": {}, "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "9b1c5be5", + "metadata": {}, "source": [ - "#####sdfasdfasdg#########afsdfasdfsadfasdfasdfasdfasdfasdfsdfdsa" + "## Tree Breadth First Search\n" ] }, { "cell_type": "markdown", - "id": "42c30436", + "id": "b378a4b6", "metadata": {}, "source": [ - "## Precomputation\n" + "## Tree Depth First Search\n" ] }, { "cell_type": "markdown", - "id": "07bee308", + "id": "90975236", "metadata": {}, "source": [ - "- For questions where summation or multiplication of a subarray is involved, pre-computation using hashing or a prefix/suffix sum/product might be useful.\n" + "## Graphs\n" + ] + }, + { + "cell_type": "markdown", + "id": "82906705", + "metadata": {}, + "source": [ + "## Island (Matrix Traversal)\n" + ] + }, + { + "cell_type": "markdown", + "id": "7d726e24", + "metadata": {}, + "source": [ + "## Two Heaps\n" + ] + }, + { + "cell_type": "markdown", + "id": "0a4b727d", + "metadata": {}, + "source": [ + "## Subsets\n" + ] + }, + { + "cell_type": "markdown", + "id": "5d3d94d8", + "metadata": {}, + "source": [ + "## Modified Binary Search\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "ff247028", + "id": "9229ae9f", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## Modified Binary Search\n", + "\n", + "\"\"\"\n", + "### Modified Binary Search\n", + "\n", + "- Binary search adapted for: rotated arrays, find first/last occurrence\n", + "- Works on sorted or partially sorted data\n", + "- Time: O(log n), Space: O(1)\n", + "\"\"\"\n", + "\n", + "# Example: Search in rotated sorted array\n", + "def search_rotated_array(nums: list[int], target: int) -> int:\n", + " left, right = 0, len(nums) - 1\n", + " \n", + " while left <= right:\n", + " mid = (left + right) // 2\n", + " \n", + " if nums[mid] == target:\n", + " return mid\n", + " \n", + " # Check which side is sorted\n", + " if nums[left] <= nums[mid]:\n", + " # Left side is sorted\n", + " if nums[left] <= target < nums[mid]:\n", + " right = mid - 1\n", + " else:\n", + " left = mid + 1\n", + " else:\n", + " # Right side is sorted\n", + " if nums[mid] < target <= nums[right]:\n", + " left = mid + 1\n", + " else:\n", + " right = mid - 1\n", + " \n", + " return -1\n", + "\n", + "print(search_rotated_array([4,5,6,7,0,1,2], 0)) # 4\n", + "\n", + "# Example: Find first and last occurrence\n", + "def find_first_last(nums: list[int], target: int) -> list[int]:\n", + " def find_first():\n", + " left, right = 0, len(nums) - 1\n", + " result = -1\n", + " while left <= right:\n", + " mid = (left + right) // 2\n", + " if nums[mid] == target:\n", + " result = mid\n", + " right = mid - 1\n", + " elif nums[mid] < target:\n", + " left = mid + 1\n", + " else:\n", + " right = mid - 1\n", + " return result\n", + " \n", + " def find_last():\n", + " left, right = 0, len(nums) - 1\n", + " result = -1\n", + " while left <= right:\n", + " mid = (left + right) // 2\n", + " if nums[mid] == target:\n", + " result = mid\n", + " left = mid + 1\n", + " elif nums[mid] < target:\n", + " left = mid + 1\n", + " else:\n", + " right = mid - 1\n", + " return result\n", + " \n", + " return [find_first(), find_last()]\n", + "\n", + "print(find_first_last([5,7,7,8,8,10], 8)) # [3, 4]" + ] }, { "cell_type": "markdown", - "id": "cbf4b849", + "id": "42465298", "metadata": {}, "source": [ - "## Index as a hash key\n" + "## Bitwise XOR\n" ] }, { "cell_type": "markdown", - "id": "fd2372f3", + "id": "22b2d840", "metadata": {}, "source": [ - "- If you are given a sequence and the interviewer asks for O(1) space, it might be possible to use the array itself as a hash table.\n", - "- For example, if the array only has values from 1 to N, where N is the length of the array, negate the value at that index (minus one) to indicate presence of that number.\n" + "## Top 'K' Elements\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "4d69a7c2", + "id": "31825f29", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## Top 'K' Elements\n", + "\n", + "\"\"\"\n", + "### Top 'K' Elements\n", + "\n", + "- Find k largest/smallest elements\n", + "- Use heap: min-heap for k largest, max-heap for k smallest\n", + "- Time: O(n log k), Space: O(k)\n", + "- More efficient than sorting when k << n\n", + "\"\"\"\n", + "\n", + "import heapq\n", + "\n", + "# Example: K Largest Elements\n", + "def find_k_largest(nums: list[int], k: int) -> list[int]:\n", + " return heapq.nlargest(k, nums)\n", + "\n", + "print(find_k_largest([3, 1, 5, 12, 2, 11], 3)) # [12, 11, 5]\n", + "\n", + "# Example: K Closest Points to Origin\n", + "def k_closest_points(points: list[list[int]], k: int) -> list[list[int]]:\n", + " # Min heap of (distance, point)\n", + " min_heap = []\n", + " \n", + " for point in points:\n", + " dist = point[0]**2 + point[1]**2\n", + " heapq.heappush(min_heap, (dist, point))\n", + " \n", + " result = []\n", + " for _ in range(k):\n", + " result.append(heapq.heappop(min_heap)[1])\n", + " \n", + " return result\n", + "\n", + "print(k_closest_points([[1,3],[2,3],[5,-1],[-2,4]], 2))\n", + "# [[1,3],[2,3]]" + ] + }, + { + "cell_type": "markdown", + "id": "95985c70", + "metadata": {}, + "source": [ + "## K-way Merge\n" + ] + }, + { + "cell_type": "markdown", + "id": "8b4536e1", + "metadata": {}, + "source": [ + "## Greedy Algorithms\n" + ] + }, + { + "cell_type": "markdown", + "id": "7b8c7aa5", + "metadata": {}, + "source": [ + "## 0/1 Knapsack\n" + ] + }, + { + "cell_type": "markdown", + "id": "3aded578", + "metadata": {}, + "source": [ + "## Fibonacci Numbers\n" + ] + }, + { + "cell_type": "markdown", + "id": "a09da022", + "metadata": {}, + "source": [ + "## Palindromic Subsequence\n" + ] + }, + { + "cell_type": "markdown", + "id": "7edef10d", + "metadata": {}, + "source": [ + "## Backtracking\n" + ] + }, + { + "cell_type": "markdown", + "id": "a13c0398", + "metadata": {}, + "source": [ + "## Trie\n" + ] }, { "cell_type": "markdown", - "id": "6e5a636e", + "id": "aeaef085", "metadata": {}, "source": [ - "## Traversing the array more than once\n" + "## Topological Sort\n" ] }, { "cell_type": "markdown", - "id": "55aef46f", + "id": "a63bd79b", "metadata": {}, "source": [ - "- This might be obvious, but traversing the array twice/thrice (as long as fewer than n times) is still O(n).\n", - "- Sometimes traversing the array more than once can help you solve the problem while keeping the time complexity to O(n).\n" + "## Union Find\n" + ] + }, + { + "cell_type": "markdown", + "id": "2ce5aaba", + "metadata": {}, + "source": [ + "## Ordered Set\n" + ] + }, + { + "cell_type": "markdown", + "id": "8b3e26a4", + "metadata": {}, + "source": [ + "## Prefix Sum\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "f1faad73", + "id": "0d1e4fbe", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "## Prefix Sum\n", + "\n", + "\"\"\"\n", + "### Prefix Sum\n", + "\n", + "- Precompute cumulative sum up to each index\n", + "- Query range sum in O(1) after O(n) preprocessing\n", + "- prefix_sum[i] = sum of all elements from 0 to i\n", + "- Range sum [i, j] = prefix_sum[j] - prefix_sum[i-1]\n", + "\"\"\"\n", + "\n", + "# Example: Range Sum Query\n", + "class PrefixSumArray:\n", + " def __init__(self, nums: list[int]):\n", + " self.prefix = [0] * (len(nums) + 1)\n", + " for i in range(len(nums)):\n", + " self.prefix[i + 1] = self.prefix[i] + nums[i]\n", + " \n", + " def range_sum(self, left: int, right: int) -> int:\n", + " return self.prefix[right + 1] - self.prefix[left]\n", + "\n", + "nums = [1, 2, 3, 4, 5]\n", + "ps = PrefixSumArray(nums)\n", + "print(ps.range_sum(1, 3)) # 2+3+4 = 9\n", + "\n", + "# Example: Subarray sum equals K\n", + "def subarray_sum(nums: list[int], k: int) -> int:\n", + " count = 0\n", + " prefix_sum = 0\n", + " sum_count = {0: 1} # Map of sum -> frequency\n", + " \n", + " for num in nums:\n", + " prefix_sum += num\n", + " \n", + " # Check if (prefix_sum - k) exists\n", + " if prefix_sum - k in sum_count:\n", + " count += sum_count[prefix_sum - k]\n", + " \n", + " sum_count[prefix_sum] = sum_count.get(prefix_sum, 0) + 1\n", + " \n", + " return count\n", + "\n", + "print(subarray_sum([1, 1, 1], 2)) # 2 (indices [0,1] and [1,2])" + ] + }, + { + "cell_type": "markdown", + "id": "8c644940", + "metadata": {}, + "source": [ + "## Multi-threaded\n" + ] }, { "cell_type": "markdown", @@ -220,7 +988,7 @@ "id": "ea0dcaa5", "metadata": {}, "source": [ - "## Contains Duplicate" + "## Contains Duplicate\n" ] }, { @@ -316,7 +1084,7 @@ "id": "9510f012", "metadata": {}, "source": [ - "## Pangram" + "## Pangram\n" ] }, { @@ -385,7 +1153,7 @@ "id": "368eb8d1", "metadata": {}, "source": [ - "## Reverse Vowels" + "## Reverse Vowels\n" ] }, { @@ -395,80 +1163,172 @@ "metadata": {}, "outputs": [], "source": [ - "\"\"\"\nGiven a string s, reverse only all the vowels in the string and return it.\n\nThe vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, more than once.\n\nExample 1:\n\nInput: s= \"hello\"\nOutput: \"holle\"\n\nExample 2:\n\nInput: s= \"AEIOU\"\nOutput: \"UOIEA\"\n\nExample 3:\n\nInput: s= \"DesignGUrus\"\nOutput: \"DusUgnGires\"\nConstraints:\n\n1 <= s.length <= 3 * 105\ns consist of printable ASCII characters.\n\"\"\"\n\n# Understanding\n# - Reiterate Question + requirements to ensure you understand the problem\n# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the vowel found at len - index of current vowel in the list\n\n# Approach\n# - Describe your approach + pseudocode to solving the problem.\n# Two-pointer approach:\n# 1. Convert string to list (strings are immutable in Python)\n# 2. Use two pointers: left starting at 0, right starting at end\n# 3. Move left pointer until we find a vowel\n# 4. Move right pointer until we find a vowel\n# 5. Swap the vowels at left and right positions\n# 6. Continue until pointers meet\n# 7. Convert list back to string and return\n\n# Complexity \n# - Add your time complexity here\n# O(n) to loop through input string with two pointers\n# - Add your space complexity here\n# O(n) to store the string as a list for modification\n\nclass Solution:\n def reverseVowels(self, s: str) -> str:\n vowels = set(\"aeiouAEIOU\")\n s_list = list(s) # Convert to list since strings are immutable\n left, right = 0, len(s) - 1\n \n while left < right:\n # Move left pointer until we find a vowel\n while left < right and s_list[left] not in vowels:\n left += 1\n \n # Move right pointer until we find a vowel\n while left < right and s_list[right] not in vowels:\n right -= 1\n \n # Swap the vowels\n if left < right:\n s_list[left], s_list[right] = s_list[right], s_list[left]\n left += 1\n right -= 1\n \n return ''.join(s_list)\n" + "\"\"\"\n", + "Given a string s, reverse only all the vowels in the string and return it.\n", + "\n", + "The vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, more than once.\n", + "\n", + "Example 1:\n", + "\n", + "Input: s= \"hello\"\n", + "Output: \"holle\"\n", + "\n", + "Example 2:\n", + "\n", + "Input: s= \"AEIOU\"\n", + "Output: \"UOIEA\"\n", + "\n", + "Example 3:\n", + "\n", + "Input: s= \"DesignGUrus\"\n", + "Output: \"DusUgnGires\"\n", + "Constraints:\n", + "\n", + "1 <= s.length <= 3 * 105\n", + "s consist of printable ASCII characters.\n", + "\"\"\"\n", + "\n", + "# Understanding\n", + "# - Reiterate Question + requirements to ensure you understand the problem\n", + "# given a string s we want to reverse every vowel found in that string. Reversing means replacing the current vowel with the first vowel we find at the end of the string\n", + "# the output should also be case sensitive\n", + "\n", + "# Approach\n", + "# - Describe your approach + psuedocode to solving the problem.\n", + "# Brute Force:\n", + "# 1. start and end pointers on the input string\n", + "# 1b. create a string with all vowels lower and upper\n", + "# 2. move pointers only if they are not vowels and they are not equal. \n", + " # a. if both pointers on vowel swap the vowel\n", + " # b. if left pointer on vowel, move right to left until it hits vowel (vice versa)\n", + "# 3. return string\n", + "\n", + "# Code\n", + "# - Code the solution from pseudocode\n", + "\n", + "# Complexity \n", + "# - Add your time complexity here\n", + "# O(n) to loop through input string\n", + "# - Add your space complexity here\n", + "# O(1) since max 5 vowels to store in set ds\n", + "\n", + "# Optimized:\n", + "\n", + "class Solution:\n", + " def reverseVowels(self, s: str) -> str:\n", + " vowels = \"aeiouAEIOU\"\n", + " left = 0\n", + " right = len(s) - 1\n", + " carray = list(s)\n", + " while left < right:\n", + " if carray[left] not in vowels:\n", + " left+=1\n", + " elif carray[right] not in vowels:\n", + " right-=1\n", + " else:\n", + " carray[left],carray[right] = carray[right], carray[left]\n", + " left +=1\n", + " right -=1\n", + " return \"\".join(carray)" ] }, { "cell_type": "markdown", - "id": "7f389c01", + "id": "16b0d82d", "metadata": {}, "source": [ - "## Two Sum" + "## Valid Palindrome\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "baf3270d", + "id": "951ca197", "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "f07d3b89", - "metadata": {}, "source": [ - "## Best Time to Buy and Sell Stock\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e9a21f97", - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'List' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)\n", - "Cell \u001b[0;32mIn[1], line 11\u001b[0m\n", - "\u001b[1;32m 2\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n", - "\u001b[1;32m 3\u001b[0m \u001b[38;5;124;03mQ: You are given an array prices where prices[i] is the price of a given stock on the ith day.\u001b[39;00m\n", - "\u001b[1;32m 4\u001b[0m \n", - "\u001b[0;32m (...)\u001b[0m\n", - "\u001b[1;32m 7\u001b[0m \u001b[38;5;124;03mReturn the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.\u001b[39;00m\n", - "\u001b[1;32m 8\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n", - "\u001b[1;32m 10\u001b[0m \u001b[38;5;66;03m#A: \u001b[39;00m\n", - "\u001b[0;32m---> 11\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmaxProfit\u001b[39m(\u001b[38;5;28mself\u001b[39m, prices: List[\u001b[38;5;28mint\u001b[39m]) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28mint\u001b[39m:\n", - "\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n", - "\n", - "\u001b[0;31mNameError\u001b[0m: name 'List' is not defined" - ] - } - ], - "source": [ - "from typing import List\n", - "\"\"\"\n", - "Q: You are given an array prices where prices[i] is the price of a given stock on the ith day.\n", - "\n", - "You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.\n", - "\n", - "Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.\n", - "\"\"\"\n", - "\n", - "#A: \n", - "def maxProfit(self, prices: List[int]) -> int:\n", - " pass" + "\"\"\"\n", + "A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.\n", + "\n", + "Given a string s, return true if it is a palindrome, or false otherwise.\n", + "\n", + "Example 1:\n", + "\n", + "Input: sentence = \"A man, a plan, a canal, Panama!\"\n", + "Output: true\n", + "Explanation: \"amanaplanacanalpanama\" is a palindrome.\n", + "\n", + "Example 2:\n", + "\n", + "Input: sentence = \"Was it a car or a cat I saw?\"\n", + "Output: true\n", + "Explanation: Explanation: \"wasitacaroracatisaw\" is a palindrome.\n", + "Constraints:\n", + "\n", + "1 <= s.length <= 2 * 105\n", + "s consists only of printable ASCII characters.\n", + "\"\"\"\n", + "\n", + "# Understanding:\n", + "# - Reiterate Question + requirements to ensure you understand the problem\n", + "# I want to determine whether an input is a palindrome or not\n", + "# A palindrom is a string where after normalization (removing non-alpha chars and lowercasing chars) it reads the same forward and backward \n", + "\n", + "# Approach:\n", + "# - Describe your approach + pseudocode to solving the problem.\n", + "# Brute Force:\n", + "# I can use .isalpha and .lower to copy only the alpha num chars from the input string into a new string. \n", + "# I can then try using two pointers one at the end and one at beginning to see if the left half equals the right half of the new strings\n", + "# I will implement brute force way first to check if the soltion works and then I will see if there are any optimizations I can make\n", + "\n", + "# Code:\n", + "# - Code solution from psuedocode\n", + "\n", + "# Complexity:\n", + "# - Add your time complexity here\n", + "# - Add your space complexity here\n", + "\n", + "# Optimized:\n", + "\n", + "class Solution:\n", + " def isPalindrome(self, s: str) -> bool:\n", + " # TODO: Write your code here\n", + " cleaned = \"\"\n", + "\n", + " for char in s:\n", + " if char.isalnum():\n", + " cleaned += char.lower()\n", + " \n", + " l = 0\n", + " r = len(cleaned) - 1\n", + " \n", + " while l < r:\n", + " if cleaned[l] != cleaned[r]:\n", + " return False\n", + " l+=1\n", + " r-=1\n", + "\n", + " return True\n" ] } ], "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" } }, "nbformat": 4, diff --git a/Datastructures + Algorithms/1a_strings.ipynb b/Datastructures + Algorithms/1a_strings.ipynb new file mode 100644 index 0000000..653f8c8 --- /dev/null +++ b/Datastructures + Algorithms/1a_strings.ipynb @@ -0,0 +1,570 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f94b0f5f", + "metadata": {}, + "source": [ + "# String Implementations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "69f278f3", + "metadata": {}, + "outputs": [], + "source": [ + "# Empty string\n", + "s = \"\"\n", + "\n", + "# String with initial value\n", + "s = \"hello\"\n", + "\n", + "# String with escape sequences\n", + "s = \"hello\\nworld\" # newline\n", + "s = \"tab\\there\" # tab\n", + "s = \"quote\\\"here\" # escaped quote\n", + "\n", + "# String from other types\n", + "s = str(42) # \"42\"\n", + "s = str([1, 2, 3]) # \"[1, 2, 3]\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f6befb1", + "metadata": {}, + "outputs": [], + "source": [ + "## String Immutability\n", + "\n", + "\"\"\"\n", + "### String Immutability\n", + "\n", + "- Strings are immutable in Python\n", + "- Cannot modify individual characters\n", + "- Operations like replace() return new strings\n", + "\"\"\"\n", + "\n", + "s = \"hello\"\n", + "# s[0] = 'H' # TypeError: 'str' object does not support item assignment\n", + "\n", + "# To modify, create new string\n", + "s = \"H\" + s[1:]\n", + "print(s) # 'Hello'\n", + "\n", + "# Or use replace\n", + "s = \"hello\"\n", + "s = s.replace(\"h\", \"H\")\n", + "print(s) # 'Hello'" + ] + }, + { + "cell_type": "markdown", + "id": "450361b2", + "metadata": {}, + "source": [ + "# Methods / Operations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2f2015ff", + "metadata": {}, + "outputs": [], + "source": [ + "## Indexing & Slicing\n", + "\n", + "# Access character - O(1)\n", + "s = \"hello\"\n", + "print(s[0]) # 'h'\n", + "print(s[1]) # 'e'\n", + "print(s[-1]) # 'o' (last char)\n", + "print(s[-2]) # 'l' (second to last)\n", + "\n", + "# Slice substring - O(k) where k is slice length\n", + "print(s[1:4]) # 'ell' (indices 1,2,3)\n", + "print(s[:3]) # 'hel' (first 3)\n", + "print(s[2:]) # 'llo' (from index 2 to end)\n", + "print(s[::2]) # 'hlo' (every 2nd char)\n", + "print(s[::-1]) # 'olleh' (reversed)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b86094d", + "metadata": {}, + "outputs": [], + "source": [ + "## .len() / length\n", + "\n", + "\"\"\"\n", + "### len(string)\n", + "\n", + "- Return number of characters in string - O(1)\n", + "\"\"\"\n", + "\n", + "s = \"hello\"\n", + "print(len(s)) # 5\n", + "print(len(\"\")) # 0\n", + "print(len(\"hello world\")) # 11 (includes space)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd478c50", + "metadata": {}, + "outputs": [], + "source": [ + "## .upper() / .lower() / .title() / .capitalize()\n", + "\n", + "\"\"\"\n", + "### Case Methods\n", + "\n", + "- .upper(): convert to uppercase - O(n)\n", + "- .lower(): convert to lowercase - O(n)\n", + "- .title(): capitalize first letter of each word - O(n)\n", + "- .capitalize(): capitalize first letter only - O(n)\n", + "- .casefold(): aggressive lowercase for comparisons - O(n)\n", + "\"\"\"\n", + "\n", + "s = \"Hello World\"\n", + "print(s.upper()) # 'HELLO WORLD'\n", + "print(s.lower()) # 'hello world'\n", + "print(s.title()) # 'Hello World'\n", + "print(s.capitalize()) # 'Hello world'\n", + "\n", + "# Unicode example\n", + "s = \"Straße\"\n", + "print(s.lower()) # 'straße'\n", + "print(s.casefold()) # 'strasse' (stronger)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "050d10af", + "metadata": {}, + "outputs": [], + "source": [ + "## .strip() / .lstrip() / .rstrip()\n", + "\n", + "\"\"\"\n", + "### Strip Methods\n", + "\n", + "- .strip(): remove leading/trailing whitespace - O(n)\n", + "- .lstrip(): remove leading (left) whitespace - O(n)\n", + "- .rstrip(): remove trailing (right) whitespace - O(n)\n", + "- Can specify characters to strip\n", + "\"\"\"\n", + "\n", + "s = \" hello world \\n\"\n", + "print(f\"'{s.strip()}'\") # 'hello world'\n", + "print(f\"'{s.lstrip()}'\") # 'hello world \\n'\n", + "print(f\"'{s.rstrip()}'\") # ' hello world'\n", + "\n", + "# Strip specific characters\n", + "s = \"~~--data--~~\"\n", + "print(s.strip(\"~-\")) # 'data'\n", + "print(s.lstrip(\"~\")) # '--data--~~'\n", + "print(s.rstrip(\"-~\")) # '~~--data'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "060b7507", + "metadata": {}, + "outputs": [], + "source": [ + "## .split() / .rsplit()\n", + "\n", + "\"\"\"\n", + "### Split Methods\n", + "\n", + "- .split(sep): split by separator (default whitespace) - O(n)\n", + "- .rsplit(sep): split from right - O(n)\n", + "- maxsplit parameter limits splits\n", + "\"\"\"\n", + "\n", + "s = \"a,b,c,d\"\n", + "print(s.split(\",\")) # ['a', 'b', 'c', 'd']\n", + "\n", + "s = \"hello world python\"\n", + "print(s.split()) # ['hello', 'world', 'python']\n", + "\n", + "s = \"a-b-c-d-e\"\n", + "print(s.split(\"-\", maxsplit=2)) # ['a', 'b', 'c-d-e'] (max 2 splits)\n", + "print(s.rsplit(\"-\", maxsplit=1)) # ['a-b-c-d', 'e'] (split from right)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d64ff7c", + "metadata": {}, + "outputs": [], + "source": [ + "## .join()\n", + "\n", + "\"\"\"\n", + "### .join()\n", + "\n", + "- Join iterable with string as separator - O(n)\n", + "- More efficient than + for multiple strings\n", + "\"\"\"\n", + "\n", + "words = ['hello', 'world', 'python']\n", + "s = \" \".join(words)\n", + "print(s) # 'hello world python'\n", + "\n", + "chars = ['a', 'b', 'c']\n", + "s = \"-\".join(chars)\n", + "print(s) # 'a-b-c'\n", + "\n", + "# Efficient for building strings\n", + "result = \"\".join(['a', 'b', 'c'])\n", + "print(result) # 'abc'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b59ae15", + "metadata": {}, + "outputs": [], + "source": [ + "## .find() / .rfind() / .index()\n", + "\n", + "\"\"\"\n", + "### Search Methods\n", + "\n", + "- .find(sub): return index of substring, -1 if not found - O(n*m)\n", + "- .rfind(sub): find from right - O(n*m)\n", + "- .index(sub): like find but raises ValueError if not found - O(n*m)\n", + "\"\"\"\n", + "\n", + "s = \"hello world hello\"\n", + "print(s.find(\"o\")) # 4 (first 'o')\n", + "print(s.rfind(\"o\")) # 14 (last 'o')\n", + "print(s.find(\"world\")) # 6\n", + "print(s.find(\"xyz\")) # -1 (not found)\n", + "\n", + "# index raises error\n", + "print(s.index(\"world\")) # 6\n", + "try:\n", + " s.index(\"xyz\")\n", + "except ValueError:\n", + " print(\"Substring not found\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29c49363", + "metadata": {}, + "outputs": [], + "source": [ + "## .count()\n", + "\n", + "\"\"\"\n", + "### .count(sub)\n", + "\n", + "- Count non-overlapping occurrences of substring - O(n)\n", + "\"\"\"\n", + "\n", + "s = \"hello world hello\"\n", + "print(s.count(\"hello\")) # 2\n", + "print(s.count(\"l\")) # 3\n", + "print(s.count(\"o\")) # 2\n", + "print(s.count(\"xyz\")) # 0\n", + "\n", + "# With overlapping (count is non-overlapping)\n", + "s = \"aaa\"\n", + "print(s.count(\"aa\")) # 1 (non-overlapping)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06f2aa1b", + "metadata": {}, + "outputs": [], + "source": [ + "## .replace()\n", + "\n", + "\"\"\"\n", + "### .replace(old, new, count)\n", + "\n", + "- Replace occurrences of substring - O(n)\n", + "- count parameter limits replacements\n", + "\"\"\"\n", + "\n", + "s = \"hello world hello\"\n", + "print(s.replace(\"hello\", \"hi\")) # 'hi world hi'\n", + "print(s.replace(\"hello\", \"hi\", 1)) # 'hi world hello' (1st only)\n", + "print(s.replace(\"o\", \"0\")) # 'hell0 w0rld hell0'\n", + "\n", + "# Empty string replacement\n", + "s = \"a,b,c\"\n", + "print(s.replace(\",\", \"\")) # 'abc'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da214726", + "metadata": {}, + "outputs": [], + "source": [ + "## .startswith() / .endswith()\n", + "\n", + "\"\"\"\n", + "### Prefix & Suffix Methods\n", + "\n", + "- .startswith(prefix): check if starts with prefix - O(m) where m is prefix length\n", + "- .endswith(suffix): check if ends with suffix - O(m)\n", + "- Can accept tuple of prefixes/suffixes\n", + "\"\"\"\n", + "\n", + "s = \"hello world\"\n", + "print(s.startswith(\"hello\")) # True\n", + "print(s.startswith(\"bye\")) # False\n", + "print(s.endswith(\"world\")) # True\n", + "print(s.endswith(\"xyz\")) # False\n", + "\n", + "# Multiple prefixes\n", + "print(s.startswith((\"hello\", \"hi\"))) # True\n", + "print(s.endswith((\".txt\", \".py\"))) # False\n", + "\n", + "# Useful for file checks\n", + "filename = \"document.pdf\"\n", + "print(filename.endswith((\".pdf\", \".doc\", \".docx\"))) # True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11bfdfc2", + "metadata": {}, + "outputs": [], + "source": [ + "## .isalpha() / .isdigit() / .isalnum() / .isspace()\n", + "\n", + "\"\"\"\n", + "### Character Check Methods\n", + "\n", + "- .isalpha(): all characters are alphabetic - O(n)\n", + "- .isdigit(): all characters are digits - O(n)\n", + "- .isalnum(): all characters are alphanumeric - O(n)\n", + "- .isspace(): all characters are whitespace - O(n)\n", + "- .isdecimal(): all characters are decimal digits - O(n)\n", + "- .isnumeric(): all characters are numeric - O(n)\n", + "- .istitle(): first letter of each word is uppercase - O(n)\n", + "\"\"\"\n", + "\n", + "print(\"hello\".isalpha()) # True\n", + "print(\"hello123\".isalpha()) # False\n", + "print(\"hello123\".isalnum()) # True\n", + "\n", + "print(\"12345\".isdigit()) # True\n", + "print(\"12.45\".isdigit()) # False (has dot)\n", + "\n", + "print(\" \\n\\t\".isspace()) # True\n", + "print(\"hello world\".isspace()) # False\n", + "\n", + "print(\"Hello World\".istitle()) # True\n", + "print(\"hello world\".istitle()) # False\n", + "\n", + "# Unicode digits nuance\n", + "print(\"Ⅳ\".isnumeric()) # True (Roman numeral)\n", + "print(\"١٢٣\".isdecimal()) # True (Arabic-Indic digits)\n", + "print(\"١٢٣\".isdigit()) # True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7512a45", + "metadata": {}, + "outputs": [], + "source": [ + "## .in operator\n", + "\n", + "\"\"\"\n", + "### Substring Check (in)\n", + "\n", + "- Check if substring exists - O(n*m) worst case, O(n) average\n", + "- Returns True/False\n", + "\"\"\"\n", + "\n", + "s = \"hello world\"\n", + "print(\"hello\" in s) # True\n", + "print(\"world\" in s) # True\n", + "print(\"xyz\" in s) # False\n", + "print(\"\" in s) # True (empty string always in)\n", + "\n", + "# Case sensitive\n", + "print(\"Hello\" in s) # False\n", + "print(\"HELLO\" in s) # False\n", + "\n", + "# Useful for validation\n", + "if \"error\" in result:\n", + " print(\"Something went wrong\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0e949df", + "metadata": {}, + "outputs": [], + "source": [ + "## String Formatting\n", + "\n", + "\"\"\"\n", + "### String Formatting Methods\n", + "\n", + "- f-strings (f\"...\"): most modern and efficient - O(n)\n", + "- .format(): older method - O(n)\n", + "- % operator: oldest method - O(n)\n", + "\"\"\"\n", + "\n", + "# f-strings (recommended)\n", + "name = \"Alice\"\n", + "age = 30\n", + "print(f\"Name: {name}, Age: {age}\") # 'Name: Alice, Age: 30'\n", + "print(f\"Calculation: {2 + 3}\") # 'Calculation: 5'\n", + "print(f\"Name: {name.upper()}\") # 'Name: ALICE'\n", + "\n", + "# Format specifications\n", + "value = 3.14159\n", + "print(f\"{value:.2f}\") # '3.14' (2 decimals)\n", + "print(f\"{42:05d}\") # '00042' (zero padded)\n", + "\n", + "# .format() method\n", + "print(\"Name: {}, Age: {}\".format(name, age))\n", + "print(\"Name: {0}, Age: {1}\".format(name, age))\n", + "\n", + "# % operator (old style, avoid)\n", + "print(\"Name: %s, Age: %d\" % (name, age))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4653f84f", + "metadata": {}, + "outputs": [], + "source": [ + "## Multiline Strings\n", + "\n", + "\"\"\"\n", + "### Multiline Strings\n", + "\n", + "- Triple-quoted strings for multiline content\n", + "- Preserves newlines\n", + "\"\"\"\n", + "\n", + "# Multiline string\n", + "text = \"\"\"\n", + "This is a multiline\n", + "string that spans\n", + "multiple lines.\n", + "\"\"\"\n", + "print(text)\n", + "\n", + "# Useful for docstrings\n", + "def my_function():\n", + " \"\"\"\n", + " This is a docstring.\n", + " \n", + " It can span multiple lines.\n", + " \"\"\"\n", + " pass\n", + "\n", + "# Can use \\ to continue line without newline\n", + "text = \"This is a very long string that \" \\\n", + " \"continues on the next line\"\n", + "print(text)" + ] + }, + { + "cell_type": "markdown", + "id": "8a353d21", + "metadata": {}, + "source": [ + "# Corner Cases TODO add examples for each case" + ] + }, + { + "cell_type": "markdown", + "id": "d4e7b02a", + "metadata": {}, + "source": [ + "- Empty array []\n", + "- Single or two elements\n", + "- All equal values (ties!)\n", + "- Already sorted vs reverse sorted\n", + "- Large values / potential overflow (use Python big ints, but be mindful)\n", + "- Negative numbers / zeros (esp. in products, prefix sums, Kadane)\n", + "- Duplicates (affects two-sum, set logic, binary search bounds)\n", + "- Off-by-one in slicing (half-open ranges [l, r) vs closed)\n", + "- In-place updates while iterating (iterate on indices or a copy)" + ] + }, + { + "cell_type": "markdown", + "id": "f6005fda", + "metadata": {}, + "source": [ + "# Techniques" + ] + }, + { + "cell_type": "markdown", + "id": "dc1eed72", + "metadata": {}, + "source": [ + "- fill in as you encounter through problem solving" + ] + }, + { + "cell_type": "markdown", + "id": "5843d284", + "metadata": {}, + "source": [ + "# Practice Projects" + ] + }, + { + "cell_type": "markdown", + "id": "36f82801", + "metadata": {}, + "source": [ + "- use this to practice multiple techniques + operations in the form of a project. Try to recall everything from memory before looking up\n", + "- create another ipynb notebook with the same format as this for the project" + ] + }, + { + "cell_type": "markdown", + "id": "05b965d1", + "metadata": {}, + "source": [ + "- Example projects TODO" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Datastructures + Algorithms/1a_lists_strings.ipynb b/Datastructures + Algorithms/1b_lists.ipynb similarity index 55% rename from Datastructures + Algorithms/1a_lists_strings.ipynb rename to Datastructures + Algorithms/1b_lists.ipynb index 3b90d32..c2ad4a8 100644 --- a/Datastructures + Algorithms/1a_lists_strings.ipynb +++ b/Datastructures + Algorithms/1b_lists.ipynb @@ -5,7 +5,7 @@ "id": "9db9da09", "metadata": {}, "source": [ - "# Implementations" + "# List Implementations" ] }, { @@ -64,22 +64,6 @@ "# Methods / Operations" ] }, - { - "cell_type": "markdown", - "id": "5e494587", - "metadata": {}, - "source": [ - "## Access / Indexing" - ] - }, - { - "cell_type": "markdown", - "id": "cb156c05", - "metadata": {}, - "source": [ - "- Access an element from the list" - ] - }, { "cell_type": "code", "execution_count": null, @@ -98,11 +82,7 @@ "# Indexing\n", "\n", "fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple']\n", - "print(fruits[3])\n", - "\n", - "word = 'Python'\n", - "print(word[0])\n", - "print(word[5])" + "print(fruits[3])" ] }, { @@ -122,24 +102,37 @@ "source": [ "# Negative index\n", "\n", - "print(fruits[-1])\n", - "print(word[-1])" + "print(fruits[-1])" ] }, { - "cell_type": "markdown", - "id": "491d66d5", - "metadata": {}, - "source": [ - "## Slicing " - ] - }, - { - "cell_type": "markdown", - "id": "df8bcc0b", + "cell_type": "code", + "execution_count": null, + "id": "eedaff53", "metadata": {}, + "outputs": [], "source": [ - "- TODO" + "# .pop([i])\n", + "\n", + "\"\"\"\n", + "### .pop([i])\n", + "\n", + "- Remove and return item at index i (default last)\n", + "- Raises IndexError if list is empty\n", + "- O(1) if removing last element, O(n) otherwise\n", + "\"\"\"\n", + "\n", + "fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple']\n", + "\n", + "# Pop last item - O(1)\n", + "last = fruits.pop()\n", + "print(f\"Popped: {last}\") # 'apple'\n", + "print(fruits) # ['orange', 'apple', 'pear', 'banana', 'kiwi']\n", + "\n", + "# Pop specific index - O(n)\n", + "second = fruits.pop(1)\n", + "print(f\"Popped at index 1: {second}\") # 'apple'\n", + "print(fruits) # ['orange', 'pear', 'banana', 'kiwi']" ] }, { @@ -155,41 +148,12 @@ "print(fruits[1:4]) # ['apple','pear','banana']\n", "print(fruits[:3]) # first 3\n", "print(fruits[::2]) # step 2\n", - "print(fruits[::-1]) # reversed copy\n", - "\n", - "word = 'Savestate'\n", - "word[0:2]\n", - "\n", - "# character from the beginning to position 2 (excluded)\n", - "print(word[:2])\n", - "\n", - "# characters from position 4 (included) to the end\n", - "print(word[4:])\n", - "\n", - "# characters from the second-last to the end\n", - "print(word[-2:])" - ] - }, - { - "cell_type": "markdown", - "id": "da0d5ace", - "metadata": {}, - "source": [ - "## .append(x)" - ] - }, - { - "cell_type": "markdown", - "id": "00fe156c", - "metadata": {}, - "source": [ - " - Add an item to the end of a list\n", - " - Similar to a[len(a):] = [x]" + "print(fruits[::-1]) # reversed copy" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "e43984ef", "metadata": {}, "outputs": [ @@ -202,32 +166,21 @@ } ], "source": [ + "## .append(x)\n", + "\n", + "\"\"\"\n", + " - Add an item to the end of a list\n", + " - Similar to a[len(a):] = [x]\n", + "\"\"\"\n", "# append to end - O(1)\n", "\n", "fruits.append('grape')\n", "print(fruits)" ] }, - { - "cell_type": "markdown", - "id": "477271f5", - "metadata": {}, - "source": [ - "## .extend(iterable)" - ] - }, - { - "cell_type": "markdown", - "id": "e239c7de", - "metadata": {}, - "source": [ - "- Extend the list by appending all the items from the iterable. \n", - "- Similar to a[len(a):] = iterable." - ] - }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "5f9c5d38", "metadata": {}, "outputs": [ @@ -240,28 +193,18 @@ } ], "source": [ + "## .extend(iterable)\n", + "\n", + "\"\"\"\n", + "- Extend the list by appending all the items from the iterable. \n", + "- Similar to a[len(a):] = iterable.\n", + "\"\"\"\n", "# Concatenate many at once - O(k)\n", + "\n", "fruits.extend(['x','y'])\n", "print(fruits)" ] }, - { - "cell_type": "markdown", - "id": "43e341c0", - "metadata": {}, - "source": [ - "## .insert(i,x)" - ] - }, - { - "cell_type": "markdown", - "id": "2c3d8db5", - "metadata": {}, - "source": [ - "- Insert an item at a given position in a list.\n", - "- i - index of the element before which to insert\n" - ] - }, { "cell_type": "code", "execution_count": null, @@ -277,6 +220,12 @@ } ], "source": [ + "## .insert(i,x)\n", + "\n", + "\"\"\"\n", + "- Insert an item at a given position in a list.\n", + "- i - index of the element before which to insert\n", + "\"\"\"\n", "# append to front - O(n)\n", "\n", "fruits.insert(0,'passionfruit')\n", @@ -301,7 +250,7 @@ "# append within the list - O(n) since have to shift all elements to the right to maintain size of array\n", "\n", "fruits.insert(2,'plum')\n", - "print(fruits)\n" + "print(fruits)" ] }, { @@ -325,22 +274,6 @@ "print(fruits)" ] }, - { - "cell_type": "markdown", - "id": "5b55a4b0", - "metadata": {}, - "source": [ - "## .remove(x)" - ] - }, - { - "cell_type": "markdown", - "id": "103c5591", - "metadata": {}, - "source": [ - "- Remove the first item from the list whose value is equal to x" - ] - }, { "cell_type": "code", "execution_count": null, @@ -348,6 +281,12 @@ "metadata": {}, "outputs": [], "source": [ + "## .remove(x)\n", + "\n", + "\"\"\"\n", + "## .remove(x)\n", + "- Remove the first item from the list whose value is equal to x\n", + "\"\"\"\n", "# remove within list - O(n) since have to shift all elements to left to maintain size of array\n", "# remove at end - O(1)\n", "\n", @@ -355,212 +294,230 @@ "print(fruits)" ] }, - { - "cell_type": "markdown", - "id": "fbd3bbdc", - "metadata": {}, - "source": [ - "## .index(x)" - ] - }, - { - "cell_type": "markdown", - "id": "07719831", - "metadata": {}, - "source": [ - "- Return zero-based index of the first occurrence of x in the list. \n", - "- Raises a ValueError if there is no such item." - ] - }, { "cell_type": "code", "execution_count": null, - "id": "118ab094", + "id": "afd89787", "metadata": {}, "outputs": [], "source": [ - "print(fruits.index('pear'))\n", - "print(fruits.index('banana'))" - ] - }, - { - "cell_type": "markdown", - "id": "f5a60617", - "metadata": {}, - "source": [ - "## .strip()" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b4a32b5a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "hello\n", - "hello \n", - "\n", - " \t hello\n", - "data\n" - ] - } - ], - "source": [ + "## .clear()\n", + "\n", "\"\"\"\n", - "### .strip() / .lstrip() / .rstrip()\n", + "### .clear()\n", "\n", - "- Remove leading/trailing whitespace by default.\n", - "- Provide a character set to strip specific chars.\n", + "- Remove all items from the list\n", + "- List becomes empty but still exists\n", + "- O(n)\n", "\"\"\"\n", - "# (Code)\n", - "t = \" \\t hello \\n\"\n", - "print(t.strip()) # 'hello'\n", - "print(t.lstrip()) # 'hello \\n'\n", - "print(t.rstrip()) # ' \\t hello'\n", - "u = \"~~--data--~~\"\n", - "print(u.strip(\"~-\")) # 'data--' (strips any of '~' or '-' from ends)" - ] - }, - { - "cell_type": "markdown", - "id": "70d7e1f7", - "metadata": {}, - "source": [ - "## .split()" + "\n", + "fruits = ['orange', 'apple', 'pear']\n", + "fruits.clear()\n", + "print(fruits) # []\n", + "print(len(fruits)) # 0" ] }, { "cell_type": "code", "execution_count": null, - "id": "e9b0401c", + "id": "b916dba9", "metadata": {}, "outputs": [], "source": [ + "## .count(x)\n", + "\n", "\"\"\"\n", - "### .split() / .rsplit()\n", + "### .count(x)\n", "\n", - "- split() with no sep splits on any whitespace and collapses runs.\n", - "- sep specifies exact delimiter; maxsplit controls number of splits.\n", - "- rsplit() splits from the right.\n", + "- Return number of times x appears in the list\n", + "- O(n) - must scan entire list\n", "\"\"\"\n", "\n", - "line = \"a b\\tc\\n\\n d\"\n", - "print(line.split()) # ['a', 'b', 'c', 'd']\n", - "csv = \"a,b,c,d\"\n", - "print(csv.split(\",\")) # ['a', 'b', 'c', 'd']\n", - "print(csv.split(\",\", maxsplit=2)) # ['a', 'b', 'c,d']\n", - "print(csv.rsplit(\",\", maxsplit=1)) # ['a,b,c', 'd']" + "fruits = ['apple', 'banana', 'apple', 'cherry', 'apple']\n", + "count_apples = fruits.count('apple')\n", + "print(f\"Count of 'apple': {count_apples}\") # 3\n", + "\n", + "nums = [1, 2, 2, 3, 2, 4]\n", + "print(f\"Count of 2: {nums.count(2)}\") # 3\n", + "print(f\"Count of 5: {nums.count(5)}\") # 0 (not found)" ] }, { - "cell_type": "markdown", - "id": "2e99d434", + "cell_type": "code", + "execution_count": null, + "id": "118ab094", "metadata": {}, + "outputs": [], "source": [ - "## Case Methods" + "## .index(x)\n", + "\n", + "\"\"\"\n", + "## .index(x)\n", + "- Return zero-based index of the first occurrence of x in the list. \n", + "- Raises a ValueError if there is no such item.\n", + "\"\"\"\n", + "print(fruits.index('pear'))\n", + "print(fruits.index('banana'))" ] }, { "cell_type": "code", "execution_count": null, - "id": "e5e96bc1", + "id": "cf076a18", "metadata": {}, "outputs": [], "source": [ + "## .sort()\n", + "\n", "\"\"\"\n", - "## Case Methods\n", + "### .sort()\n", "\n", - "- .upper(), .lower(), .title(), .capitalize(), .casefold() (stronger lower for caseless matching).\n", + "- Sort list in-place in ascending order\n", + "- Optional: reverse=True for descending, key=func for custom sorting\n", + "- O(n log n) - uses Timsort algorithm\n", + "- Modifies original list\n", "\"\"\"\n", - "# (Code)\n", - "s = \"Straße\"\n", - "print(s.lower()) # 'straße'\n", - "print(s.casefold()) # 'strasse' (better for comparisons)\n", - "print(\"hello world\".title()) # 'Hello World'\n", - "print(\"hello world\".capitalize())# 'Hello world'" - ] - }, - { - "cell_type": "markdown", - "id": "d3b693ff", - "metadata": {}, - "source": [ - "## Count & Predicates" + "\n", + "nums = [3, 1, 4, 1, 5, 9, 2, 6]\n", + "nums.sort()\n", + "print(f\"Sorted: {nums}\") # [1, 1, 2, 3, 4, 5, 6, 9]\n", + "\n", + "# Sort descending\n", + "nums = [3, 1, 4, 1, 5, 9]\n", + "nums.sort(reverse=True)\n", + "print(f\"Descending: {nums}\") # [9, 5, 4, 3, 1, 1]\n", + "\n", + "# Sort by custom key\n", + "words = ['banana', 'pie', 'Washington', 'book']\n", + "words.sort(key=str.lower) # case-insensitive\n", + "print(f\"Case-insensitive: {words}\")\n", + "\n", + "# Sort by length\n", + "words.sort(key=len)\n", + "print(f\"By length: {words}\")\n", + "\n", + "# Sort tuples by second element\n", + "pairs = [(1, 'b'), (3, 'a'), (2, 'c')]\n", + "pairs.sort(key=lambda x: x[1])\n", + "print(f\"By second element: {pairs}\") # [(3, 'a'), (1, 'b'), (2, 'c')]" ] }, { "cell_type": "code", "execution_count": null, - "id": "aa5e05f7", + "id": "3c0e3cfd", "metadata": {}, "outputs": [], "source": [ + "## sorted()\n", + "\n", "\"\"\"\n", - "## Count & Predicates\n", + "### sorted()\n", "\n", - "- .count(sub) occurrences.\n", - "- .isalpha(), .isalnum(), .isdigit(), .isdecimal(), .isnumeric(), .isspace(), .istitle().\n", + "- Return NEW sorted list (doesn't modify original)\n", + "- Works on any iterable\n", + "- Same parameters as .sort(): reverse, key\n", + "- O(n log n)\n", "\"\"\"\n", - "# (Code)\n", - "print(\"mississippi\".count(\"ss\")) # 2\n", - "print(\"abc\".isalpha(), \"abc123\".isalnum(), \"123\".isdigit())\n", - "print(\"Ⅳ\".isnumeric(), \"١٢٣\".isdecimal()) # True False (unicode digits nuance)\n", - "print(\"Hello World\".istitle()) # True" - ] - }, - { - "cell_type": "markdown", - "id": "2bec3dc6", - "metadata": {}, - "source": [ - "## startswith() / endswith()" + "\n", + "nums = [3, 1, 4, 1, 5, 9]\n", + "sorted_nums = sorted(nums)\n", + "print(f\"Original: {nums}\") # [3, 1, 4, 1, 5, 9] - unchanged\n", + "print(f\"Sorted: {sorted_nums}\") # [1, 1, 3, 4, 5, 9]\n", + "\n", + "# Works on any iterable\n", + "print(sorted(\"hello\")) # ['e', 'h', 'l', 'l', 'o']\n", + "print(sorted({3, 1, 2})) # [1, 2, 3]\n", + "\n", + "# Descending\n", + "print(sorted(nums, reverse=True)) # [9, 5, 4, 3, 1, 1]" ] }, { "cell_type": "code", "execution_count": null, - "id": "6ad444d5", + "id": "8418a7b6", "metadata": {}, "outputs": [], "source": [ + "## max() / min() / sum()\n", + "\n", "\"\"\"\n", - "## startswith() / endswith()\n", + "### max() / min() / sum()\n", "\n", - "- Accept tuple of prefixes/suffixes.\n", + "- max(list): largest element - O(n)\n", + "- min(list): smallest element - O(n)\n", + "- sum(list): sum of all elements - O(n)\n", + "- Optional key parameter for custom comparison\n", "\"\"\"\n", - "# (Code)\n", - "fn = \"report.csv\"\n", - "print(fn.endswith((\".csv\", \".tsv\"))) # True\n", - "print(\"http://example.com\".startswith((\"http://\", \"https://\"))) # True" - ] - }, - { - "cell_type": "markdown", - "id": "b748f251", - "metadata": {}, - "source": [ - "## partition() / rpartition()" + "\n", + "nums = [3, 1, 4, 1, 5, 9, 2, 6]\n", + "\n", + "print(f\"Max: {max(nums)}\") # 9\n", + "print(f\"Min: {min(nums)}\") # 1\n", + "print(f\"Sum: {sum(nums)}\") # 31\n", + "print(f\"Average: {sum(nums) / len(nums)}\") # 3.875\n", + "\n", + "# With key parameter\n", + "words = ['apple', 'pie', 'zoo', 'a']\n", + "longest = max(words, key=len)\n", + "shortest = min(words, key=len)\n", + "print(f\"Longest: {longest}\") # 'apple'\n", + "print(f\"Shortest: {shortest}\") # 'a'\n", + "\n", + "# With objects\n", + "students = [\n", + " {'name': 'Alice', 'score': 85},\n", + " {'name': 'Bob', 'score': 92},\n", + " {'name': 'Charlie', 'score': 78}\n", + "]\n", + "top_student = max(students, key=lambda x: x['score'])\n", + "print(f\"Top student: {top_student['name']}\") # 'Bob'" ] }, { "cell_type": "code", "execution_count": null, - "id": "ed246346", + "id": "bc006c03", "metadata": {}, "outputs": [], "source": [ + "## all() / any()\n", + "\n", "\"\"\"\n", - "## partition() / rpartition()\n", + "### all() / any()\n", "\n", - "- Split into (head, sep, tail) at first/last occurrence; always returns 3-tuple.\n", + "- all(iterable): True if all elements are truthy - O(n)\n", + "- any(iterable): True if any element is truthy - O(n)\n", + "- all([]) returns True (vacuous truth)\n", + "- any([]) returns False\n", "\"\"\"\n", - "# (Code)\n", - "print(\"key=value\".partition(\"=\")) # ('key', '=', 'value')\n", - "print(\"a=b=c\".rpartition(\"=\")) # ('a=b', '=', 'c')" + "\n", + "# all() examples\n", + "nums = [2, 4, 6, 8]\n", + "print(all(x % 2 == 0 for x in nums)) # True (all even)\n", + "\n", + "nums = [2, 4, 5, 8]\n", + "print(all(x % 2 == 0 for x in nums)) # False (5 is odd)\n", + "\n", + "# any() examples\n", + "nums = [1, 3, 5, 7]\n", + "print(any(x % 2 == 0 for x in nums)) # False (none even)\n", + "\n", + "nums = [1, 3, 4, 7]\n", + "print(any(x % 2 == 0 for x in nums)) # True (4 is even)\n", + "\n", + "# Real-world use\n", + "users = [\n", + " {'name': 'Alice', 'active': True},\n", + " {'name': 'Bob', 'active': False},\n", + " {'name': 'Charlie', 'active': False}\n", + "]\n", + "has_active = any(user['active'] for user in users)\n", + "print(f\"Any active users: {has_active}\") # True\n", + "\n", + "all_active = all(user['active'] for user in users)\n", + "print(f\"All active: {all_active}\") # False" ] }, { diff --git a/Datastructures + Algorithms/1b_sets.ipynb b/Datastructures + Algorithms/1c_sets.ipynb similarity index 87% rename from Datastructures + Algorithms/1b_sets.ipynb rename to Datastructures + Algorithms/1c_sets.ipynb index abe45b9..d02693e 100644 --- a/Datastructures + Algorithms/1b_sets.ipynb +++ b/Datastructures + Algorithms/1c_sets.ipynb @@ -65,22 +65,6 @@ "# Methods / Operations" ] }, - { - "cell_type": "markdown", - "id": "b682a1d6", - "metadata": {}, - "source": [ - "- Access an element from the array" - ] - }, - { - "cell_type": "markdown", - "id": "daea8755", - "metadata": {}, - "source": [ - "## .add(x)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -88,6 +72,8 @@ "metadata": {}, "outputs": [], "source": [ + "## .add(x)\n", + "\n", "# Add single element - O(1)\n", "fruits = {'apple', 'banana', 'cherry'}\n", "fruits.add('orange')\n", @@ -97,14 +83,6 @@ "print(fruits)" ] }, - { - "cell_type": "markdown", - "id": "88b14760", - "metadata": {}, - "source": [ - "## .update(x)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -112,6 +90,8 @@ "metadata": {}, "outputs": [], "source": [ + "## .update(x)\n", + "\n", "# Add multiple elements - O(k)\n", "fruits.update(['mango', 'grape'])\n", "print(fruits)\n", @@ -121,14 +101,6 @@ "print(fruits)" ] }, - { - "cell_type": "markdown", - "id": "beb13645", - "metadata": {}, - "source": [ - "## .remove(x)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -136,6 +108,8 @@ "metadata": {}, "outputs": [], "source": [ + "## .remove(x)\n", + "\n", "\"\"\"\n", "### .remove(x)\n", "\n", @@ -151,14 +125,6 @@ "# fruits.remove('grape') # KeyError: 'grape'" ] }, - { - "cell_type": "markdown", - "id": "dea6410d", - "metadata": {}, - "source": [ - "## .discard(x)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -166,6 +132,8 @@ "metadata": {}, "outputs": [], "source": [ + "## .discard(x)\n", + "\n", "\"\"\"\n", "### .discard(x)\n", "\n", @@ -182,14 +150,6 @@ "print(fruits) # {'apple', 'cherry'}" ] }, - { - "cell_type": "markdown", - "id": "5f42fda1", - "metadata": {}, - "source": [ - "## .pop()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -197,6 +157,8 @@ "metadata": {}, "outputs": [], "source": [ + "## .pop()\n", + "\n", "\"\"\"\n", "### .pop()\n", "\n", @@ -214,17 +176,9 @@ "# fruits.pop() # KeyError: 'pop from an empty set'" ] }, - { - "cell_type": "markdown", - "id": "bc3fee5e", - "metadata": {}, - "source": [ - "## .clear()" - ] - }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "9b570bce", "metadata": {}, "outputs": [ @@ -238,6 +192,8 @@ } ], "source": [ + "## .clear()\n", + "\n", "\"\"\"\n", "### .clear()\n", "\n", @@ -251,14 +207,6 @@ "print(len(fruits)) # 0" ] }, - { - "cell_type": "markdown", - "id": "994e0c62", - "metadata": {}, - "source": [ - "## in / not in" - ] - }, { "cell_type": "code", "execution_count": null, @@ -266,6 +214,7 @@ "metadata": {}, "outputs": [], "source": [ + "## in / not in\n", "\"\"\"\n", "### in / not in\n", "\n", @@ -283,14 +232,6 @@ "print('apple' in fruits_list) # True, but O(n)" ] }, - { - "cell_type": "markdown", - "id": "5863a494", - "metadata": {}, - "source": [ - "## .union()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -298,6 +239,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .union()\n", "\"\"\"\n", "### .union() / |\n", "\n", @@ -321,14 +263,6 @@ "print(union3) # {1, 2, 3, 4, 5, 6}" ] }, - { - "cell_type": "markdown", - "id": "448d41d1", - "metadata": {}, - "source": [ - "## .intersection()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -336,6 +270,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .intersection()\n", "\"\"\"\n", "### .intersection() / &\n", "\n", @@ -359,14 +294,6 @@ "print(intersection3) # {4}" ] }, - { - "cell_type": "markdown", - "id": "0de58e7c", - "metadata": {}, - "source": [ - "## .difference()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -374,6 +301,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .difference()\n", "\"\"\"\n", "### .difference() / -\n", "\n", @@ -401,14 +329,6 @@ "print(diff4) # {1}" ] }, - { - "cell_type": "markdown", - "id": "878fb1a9", - "metadata": {}, - "source": [ - "## .symmetric_difference() / ^" - ] - }, { "cell_type": "code", "execution_count": null, @@ -416,6 +336,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .symmetric_difference() / ^\n", "\"\"\"\n", "### .symmetric_difference() / ^\n", "\n", @@ -437,14 +358,6 @@ "print(set1 ^ set2 == set2 ^ set1) # True" ] }, - { - "cell_type": "markdown", - "id": "2a373278", - "metadata": {}, - "source": [ - "## .issubset() / <=" - ] - }, { "cell_type": "code", "execution_count": null, @@ -452,6 +365,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .issubset() / <=\n", "\"\"\"\n", "### .issubset() / <=\n", "\n", @@ -473,14 +387,6 @@ "print(set().issubset(set1)) # True" ] }, - { - "cell_type": "markdown", - "id": "1b19f1a8", - "metadata": {}, - "source": [ - "## .issuperset() / >=" - ] - }, { "cell_type": "code", "execution_count": null, @@ -488,6 +394,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .issuperset() / >=\n", "\"\"\"\n", "### .issuperset() / >=\n", "\n", @@ -508,14 +415,6 @@ "print(set1.issuperset(set())) # True" ] }, - { - "cell_type": "markdown", - "id": "db339c1b", - "metadata": {}, - "source": [ - "## .isdisjoint()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -523,6 +422,7 @@ "metadata": {}, "outputs": [], "source": [ + "## .isdisjoint()\n", "\"\"\"\n", "### .isdisjoint()\n", "\n", diff --git a/Datastructures + Algorithms/1c_tuples.ipynb b/Datastructures + Algorithms/1d_tuples.ipynb similarity index 100% rename from Datastructures + Algorithms/1c_tuples.ipynb rename to Datastructures + Algorithms/1d_tuples.ipynb diff --git a/Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb b/Datastructures + Algorithms/1e_hash_table_dictionary_hash_map.ipynb similarity index 99% rename from Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb rename to Datastructures + Algorithms/1e_hash_table_dictionary_hash_map.ipynb index d9fc4a8..f916817 100644 --- a/Datastructures + Algorithms/1d_hash_table_dictionary_hash_map.ipynb +++ b/Datastructures + Algorithms/1e_hash_table_dictionary_hash_map.ipynb @@ -15,6 +15,7 @@ "metadata": {}, "outputs": [], "source": [ + "### Hash Table / Dictionary - Key-Value Mapping\n", "\"\"\"\n", "### Hash Table / Dictionary - Key-Value Mapping\n", "\n", @@ -48,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "ba2eb704", "metadata": {}, "outputs": [ @@ -65,6 +66,8 @@ } ], "source": [ + "### Complete Dictionary Implementation (Interview-Ready)\n", + "\n", "\"\"\"\n", "### Complete Dictionary Implementation (Interview-Ready)\n", "\"\"\"\n", diff --git a/Python/4_functions.ipynb b/Python/4_functions.ipynb index 6f1a1ea..28791a2 100644 --- a/Python/4_functions.ipynb +++ b/Python/4_functions.ipynb @@ -101,20 +101,6 @@ "print(t.fahrenheit) # 32.0" ] }, - { - "cell_type": "markdown", - "id": "ce7225e6", - "metadata": {}, - "source": [ - "## Doctstrings\n" - ] - }, - { - "cell_type": "markdown", - "id": "8cab42d7", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "id": "67ca0d08",