|
4 | 4 | "cell_type": "markdown",
|
5 | 5 | "metadata": {},
|
6 | 6 | "source": [
|
7 | | - "## Array sequences in Python\n", |
8 | | - "Array sequences in Python refer to 3 things: lists, tuples and strings. All the three support indexing.\n", |
| 7 | + "# Array sequences in Python\n", |
| 8 | + "Array sequences in Python include: lists, tuples and strings. All the three support indexing.\n", |
9 | 9 | "\n",
|
10 | 10 | "Each byte has a unique address. Consecutive bytes have consecutive numbers as address. Each byte can be accessed, read or written to in O(1), i.e. in constant time.\n",
|
11 | 11 | "\n",
|
12 | 12 | "A group of related variables can be stored one after another in contiguous portion of memory. This is an **array**.\n",
|
13 | 13 | "Each unicode character is represented in 2 bytes by Python. For example, the string \"SAMPLE\" will take 12 bytes.\n",
|
14 | | - "The two byte location alloted to a character is called **cell**. Now, each cell must be of same size, note necessarily 2 bytes.\n", |
| 14 | + "The two byte location alloted to a character is called **cell**. Now, each cell must be of same size, not necessarily of 2 bytes.\n", |
15 | 15 | "\n",
|
16 | 16 | "## Referential Arrays\n",
|
17 | | - "Consider an array of strings. All strings will have different length. Hence they cannot be stored in consecutive locations (discussed earlier). Hence in an array of strings, a reference of each string is stored. All references take up equal space, i.e. each cell has a reference to a string stored in another location.\n", |
| 17 | + "Consider an array of strings. All strings will have different length. Hence they cannot be stored in consecutive locations (as discussed earlier). Hence in an array of strings, a reference of each string is stored. All references take up equal space, i.e. each cell has a reference to a string stored in another location.\n", |
18 | 18 | "In python, list and tuples are referential in nature. \n",
|
19 | 19 | "\n",
|
20 | | - "In slices, it looks like a new list is formed. In reality, it holds the reference to the same objects as the original list. Change made to slice do not change the original list. The new list element now points to a new object that is different from the old list.\n", |
| 20 | + "In slices, it looks like a new list is formed. In reality, it holds the reference to the same objects as the original list. Changes made to slice do not change the original list. The new list element now points to a new object that is different from the old list.\n", |
21 | 21 | "\n",
|
22 | 22 | "## Coping Arrays\n",
|
23 | | - "```backup = list(array)``` This creates a shallow copy of the list, each elements reference the same object as the forst list. To create a new list, with elements pointing to new objects, **deepcopy** function from **copy** module can be used.\n", |
| 23 | + "```backup = list(array)``` This creates a shallow copy of the list, each elements reference the same object as the first list. To create a new list, with elements pointing to new objects, **deepcopy** function from **copy** module can be used.\n", |
24 | 24 | "\n",
|
25 | 25 | "```counter = [0] * 8``` all elements refer to the same location that holds value 0. ```counter[1] = 2``` This creates a new reference and saves it to index 1. \n",
|
26 | 26 | "\n",
|
|
52 | 52 | "multiply |O(nk)"
|
53 | 53 | ]
|
54 | 54 | },
|
| 55 | + { |
| 56 | + "cell_type": "markdown", |
| 57 | + "metadata": {}, |
| 58 | + "source": [ |
| 59 | + "A list instance often has greater capacity than specified. The following examples illustrates that size of array is increased in chunks." |
| 60 | + ] |
| 61 | + }, |
| 62 | + { |
| 63 | + "cell_type": "code", |
| 64 | + "execution_count": 1, |
| 65 | + "metadata": {}, |
| 66 | + "outputs": [ |
| 67 | + { |
| 68 | + "name": "stdout", |
| 69 | + "output_type": "stream", |
| 70 | + "text": [ |
| 71 | + "length 0 size in bytes 64\n", |
| 72 | + "length 1 size in bytes 96\n", |
| 73 | + "length 2 size in bytes 96\n", |
| 74 | + "length 3 size in bytes 96\n", |
| 75 | + "length 4 size in bytes 96\n", |
| 76 | + "length 5 size in bytes 128\n", |
| 77 | + "length 6 size in bytes 128\n", |
| 78 | + "length 7 size in bytes 128\n", |
| 79 | + "length 8 size in bytes 128\n", |
| 80 | + "length 9 size in bytes 192\n" |
| 81 | + ] |
| 82 | + } |
| 83 | + ], |
| 84 | + "source": [ |
| 85 | + "import sys\n", |
| 86 | + "\n", |
| 87 | + "n=10\n", |
| 88 | + "data = []\n", |
| 89 | + "for i in range(n):\n", |
| 90 | + " a = len(data)\n", |
| 91 | + " b = sys.getsizeof(data)\n", |
| 92 | + " print(\"length\", a, \"size in bytes\", b)\n", |
| 93 | + " data.append(n)" |
| 94 | + ] |
| 95 | + }, |
| 96 | + { |
| 97 | + "cell_type": "markdown", |
| 98 | + "metadata": {}, |
| 99 | + "source": [ |
| 100 | + "Change the value of n to 50 and run the program again. This is to understand how increase of capacity occurs. This is called dynamic array. List class in Python are dynamic arrays.\n", |
| 101 | + "\n", |
| 102 | + "In following example, a custom dynamic array is written." |
| 103 | + ] |
| 104 | + }, |
| 105 | + { |
| 106 | + "cell_type": "code", |
| 107 | + "execution_count": 2, |
| 108 | + "metadata": {}, |
| 109 | + "outputs": [], |
| 110 | + "source": [ |
| 111 | + "import ctypes\n", |
| 112 | + "\n", |
| 113 | + "class DynamicArray(object):\n", |
| 114 | + " \n", |
| 115 | + " def __init__(self):\n", |
| 116 | + " self.n = 0\n", |
| 117 | + " self.capacity = 1\n", |
| 118 | + " self.A = self.make_array(self.capacity)\n", |
| 119 | + " \n", |
| 120 | + " def __len__(self):\n", |
| 121 | + " return self.n\n", |
| 122 | + " \n", |
| 123 | + " def __getitem__(self, k):\n", |
| 124 | + " if not 0 <= k < self.n:\n", |
| 125 | + " return IndexError('K is out of bound!')\n", |
| 126 | + " return self.A[k]\n", |
| 127 | + " \n", |
| 128 | + " def append(self, ele):\n", |
| 129 | + " if self.n == self.capacity:\n", |
| 130 | + " self._resize(2*self.capacity) #2x if capacity isn't enough\n", |
| 131 | + " self.A[self.n] = ele\n", |
| 132 | + " self.n += 1\n", |
| 133 | + " \n", |
| 134 | + " def _resize(self, new_cap):\n", |
| 135 | + " B = self.make_array(new_cap)\n", |
| 136 | + " for k in range(self.n):\n", |
| 137 | + " B[k] = self.A[k]\n", |
| 138 | + " self.A = B\n", |
| 139 | + " self.capacity = new_cap\n", |
| 140 | + " \n", |
| 141 | + " def make_array(self, new_cap):\n", |
| 142 | + " return (new_cap * ctypes.py_object)()" |
| 143 | + ] |
| 144 | + }, |
| 145 | + { |
| 146 | + "cell_type": "code", |
| 147 | + "execution_count": 8, |
| 148 | + "metadata": {}, |
| 149 | + "outputs": [ |
| 150 | + { |
| 151 | + "name": "stdout", |
| 152 | + "output_type": "stream", |
| 153 | + "text": [ |
| 154 | + "length: 1\n", |
| 155 | + "length: 2\n", |
| 156 | + "second element 2\n" |
| 157 | + ] |
| 158 | + } |
| 159 | + ], |
| 160 | + "source": [ |
| 161 | + "arr = DynamicArray()\n", |
| 162 | + "arr.append(1)\n", |
| 163 | + "print(\"length:\", len(arr))\n", |
| 164 | + "arr.append(2)\n", |
| 165 | + "print(\"length:\", len(arr))\n", |
| 166 | + "print(\"second element\", arr[1])" |
| 167 | + ] |
| 168 | + }, |
| 169 | + { |
| 170 | + "cell_type": "markdown", |
| 171 | + "metadata": {}, |
| 172 | + "source": [ |
| 173 | + "## Amotized Analysis of Array\n", |
| 174 | + "This is to study how capacity is increased for dynamic arrays.\n", |
| 175 | + "\n", |
| 176 | + "## Interview Questions" |
| 177 | + ] |
| 178 | + }, |
| 179 | + { |
| 180 | + "cell_type": "code", |
| 181 | + "execution_count": 25, |
| 182 | + "metadata": {}, |
| 183 | + "outputs": [ |
| 184 | + { |
| 185 | + "name": "stdout", |
| 186 | + "output_type": "stream", |
| 187 | + "text": [ |
| 188 | + "Results of first implementation\n", |
| 189 | + "True\n", |
| 190 | + "False\n", |
| 191 | + "Results of second implementation\n", |
| 192 | + "God Dog\n", |
| 193 | + "god dog\n", |
| 194 | + "False\n", |
| 195 | + "clint eastwood old west action\n", |
| 196 | + "clinteastwood oldwestaction\n", |
| 197 | + "False\n" |
| 198 | + ] |
| 199 | + } |
| 200 | + ], |
| 201 | + "source": [ |
| 202 | + "\"\"\"\n", |
| 203 | + "Anagram Check: Given two strings if they are anagrams\n", |
| 204 | + "Ignore white spaces and capitalizations\n", |
| 205 | + "\"\"\"\n", |
| 206 | + "\n", |
| 207 | + "def anagram_check(a, b): # preferred solution\n", |
| 208 | + " a = a.lower().replace(' ','')\n", |
| 209 | + " b = b.lower().replace(' ','')\n", |
| 210 | + " return sorted(a) == sorted(b)\n", |
| 211 | + "\n", |
| 212 | + "print(\"Results of first implementation\")\n", |
| 213 | + "print(anagram_check(\"God\", \"Dog\"))\n", |
| 214 | + "print(anagram_check(\"clint eastwood\", \"olsd west action\"))\n", |
| 215 | + "\n", |
| 216 | + "def anagram_check2(a, b):\n", |
| 217 | + " print(a, b)\n", |
| 218 | + " a = a.lower().replace(' ','')\n", |
| 219 | + " b = b.lower().replace(' ','')\n", |
| 220 | + " if len(a) != len(b):\n", |
| 221 | + " return False\n", |
| 222 | + " count = {}\n", |
| 223 | + " for letter in a:\n", |
| 224 | + " if letter in count:\n", |
| 225 | + " count[letter] += 1\n", |
| 226 | + " else:\n", |
| 227 | + " count[letter] = 1\n", |
| 228 | + " for letter in b:\n", |
| 229 | + " for letter in count:\n", |
| 230 | + " count[letter] -= 1\n", |
| 231 | + " else:\n", |
| 232 | + " print(a, b)\n", |
| 233 | + " return False\n", |
| 234 | + " \n", |
| 235 | + " for k in count:\n", |
| 236 | + " if count[k] != 0:\n", |
| 237 | + " return False\n", |
| 238 | + " return True\n", |
| 239 | + "\n", |
| 240 | + "print(\"Results of second implementation\")\n", |
| 241 | + "print(anagram_check2(\"God\", \"Dog\"))\n", |
| 242 | + "print(anagram_check2(\"clint eastwood\", \"old west action\"))" |
| 243 | + ] |
| 244 | + }, |
55 | 245 | {
|
56 | 246 | "cell_type": "code",
|
57 | 247 | "execution_count": null,
|
58 | 248 | "metadata": {},
|
59 | 249 | "outputs": [],
|
60 | | - "source": [] |
| 250 | + "source": [ |
| 251 | + "\"\"\"\n", |
| 252 | + "Array Pair Sum: \n", |
| 253 | + "\"\"\"" |
| 254 | + ] |
61 | 255 | }
|
62 | 256 | ],
|
63 | 257 | "metadata": {
|
|
0 commit comments