├── README.md ├── easy ├── array_sum.py ├── circle_area.py ├── distance.py ├── distance_n_dimensions.py ├── fizzbuzz.py ├── reverse_string.py └── substring.py ├── hard ├── brainfck.py ├── lcs.py ├── maze.py ├── sort_linked_list.py └── sudoku.py ├── highlevel └── highlevel_questions.md ├── interview_handout.md ├── medium ├── 2d_array.py ├── anagrams.py ├── binary_representation.py ├── bst_level_order.py ├── bst_sorted_order.py ├── cipher_match.py ├── duplicate.py ├── fib.py ├── make_change.py ├── matching_parentheses.py ├── min_stack.py ├── permutations.py ├── powerset.py ├── print_reverse.py ├── second_largest_bst.py ├── sort.py └── target.py └── systems └── systems_questions.md /README.md: -------------------------------------------------------------------------------- 1 | # ADI Interview Workshop Problems and Solutions 2 | 3 | ## Overview 4 | 5 | The problems are divided into easy, medium, and hard. Inside each file I have 6 | noted the prerequesites for being able to answer the question easily, along 7 | with tags. 8 | 9 | For now all the solutions I've given are in Python/pseudocode (my excuse if 10 | code doesn't actually run). Feel free to add solutions in other languages. Also, 11 | the way this is set up is ideal for mock interviewers (helpful tags, solutions 12 | and hints), let me know if there are any ways you can think of to make this 13 | more helpful to people practicing. 14 | 15 | ## Contributing 16 | 17 | Please free to add notes to questions, improve solutions, and add more questions. 18 | Please don't add questions that you've heard in actual interviews unless you're 19 | sure that it is compliant with the company's policies. Thanks a lot, and hope 20 | this is useful. 21 | -------------------------------------------------------------------------------- /easy/array_sum.py: -------------------------------------------------------------------------------- 1 | # Add up the elements in an array: 2 | 3 | # tags [basic] 4 | 5 | def array_sum(array): 6 | sum = 0 7 | for element in array: 8 | sum += element 9 | return sum 10 | -------------------------------------------------------------------------------- /easy/circle_area.py: -------------------------------------------------------------------------------- 1 | # Given the radius of a circle, calculate the area. 2 | 3 | def area(radius): 4 | math.pi * pow(r, 2) 5 | -------------------------------------------------------------------------------- /easy/distance.py: -------------------------------------------------------------------------------- 1 | # Find the Euclidean distance between two coordinate points. 2 | 3 | # Tags [math] 4 | 5 | def distance(x1, x2, y1, y2): 6 | sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)) 7 | -------------------------------------------------------------------------------- /easy/distance_n_dimensions.py: -------------------------------------------------------------------------------- 1 | # Find the Euclidean distance between 2 points in n dimensions. 2 | 3 | def distance(x,y): 4 | square_sum = 0 5 | for i in range(len(x)): 6 | square_sum += pow(x[i] - y[i], 2) 7 | return sqrt(square_sum) 8 | -------------------------------------------------------------------------------- /easy/fizzbuzz.py: -------------------------------------------------------------------------------- 1 | # Write FizzBuzz. This is a function that prints out the numbers 1 to 100, and 2 | # whenever a multiple of 3 is reached, print ‘fizz’, when a multiple of 5 is 3 | # reached, print ‘buzz’, and whenever a number that is a multiple of both is 4 | # reached print ‘fizzbuzz’. 5 | 6 | # Tags: [basic] 7 | 8 | def fizzbuzz(): 9 | for i in range(100): 10 | if i % 15 == 0: 11 | print "fizzbuzz" 12 | elif i % 5 == 0: 13 | print "buzz" 14 | elif i % 3 == 0: 15 | print "fizz" 16 | else: 17 | print i 18 | -------------------------------------------------------------------------------- /easy/reverse_string.py: -------------------------------------------------------------------------------- 1 | # Write a function to reverse a string 2 | 3 | # Tags: [string] 4 | 5 | def reverse(str): 6 | reversed_string = "" 7 | for i in range(len(str), 0, -1): 8 | reversed_string += str[i] 9 | return reversed_string 10 | -------------------------------------------------------------------------------- /easy/substring.py: -------------------------------------------------------------------------------- 1 | #Given two strings, check whether the first string is a substring of the 2 | # second string. What is the runtime of your algorithm? 3 | 4 | 5 | def substring(str1, str2): 6 | is_substring = False 7 | for i in range(len(str2)): 8 | is_match = True 9 | for j in range(len(str1)): 10 | if str2[i + j] != str1[j]: 11 | is_match = False 12 | if is_match: 13 | return True 14 | return False 15 | 16 | -------------------------------------------------------------------------------- /hard/brainfck.py: -------------------------------------------------------------------------------- 1 | # Write a Brainf*ck interpreter. Brainf*ck is a language consisting of characters 2 | # “><+-[ ].,”, where the program itself represents a large array. The command 3 | # “>” moves a data pointer, which points at a given element, to the element on 4 | # the right, the command “<” moves the data pointer to the element on the left, 5 | # “+” increments the value of the element that the data pointer is pointed it, 6 | # and “-” decrements it. “,” takes raw input and puts it in the element that the 7 | # data pointer is it, and “.” outputs the value of the current element. The “]” 8 | # and “[“ characters handle looping--when a “]” is reached, if the value of the 9 | # cell that the data pointer is pointed is 0, then move the corresponding “[“ character. 10 | 11 | -------------------------------------------------------------------------------- /hard/lcs.py: -------------------------------------------------------------------------------- 1 | # Find the longest common subsequence between two strings. ie. for “abcde” and 2 | # “acccde” the longest common subsequence is “acde”. 3 | 4 | 5 | -------------------------------------------------------------------------------- /hard/maze.py: -------------------------------------------------------------------------------- 1 | # Write a maze-solver: Given a matrix of 1’s and 0’s, where a 1 indicates a 2 | # position that you can move to and a 0 one that you cannot move to, a start 3 | # coordinate, and an end coordinate, find the shortest path from the start 4 | # coordinate to the end coordinate. 5 | -------------------------------------------------------------------------------- /hard/sort_linked_list.py: -------------------------------------------------------------------------------- 1 | # Sort a linked list. 2 | -------------------------------------------------------------------------------- /hard/sudoku.py: -------------------------------------------------------------------------------- 1 | # Given a sudoku board, determine whether what has been placed on the board is 2 | # a valid solution. 3 | -------------------------------------------------------------------------------- /highlevel/highlevel_questions.md: -------------------------------------------------------------------------------- 1 | * Describe what happens in as much detail as you can when a person requests a 2 | web page. 3 | 4 | * Explain how you would build Google Docs from scratch. 5 | -------------------------------------------------------------------------------- /interview_handout.md: -------------------------------------------------------------------------------- 1 | ## ADI Interview Workshop Questions 2 | 3 | ### Couple high-level questions 4 | 5 | 1.) Describe in as much detail as possible what happens when a person requests 6 | a web page. 7 | 8 | 2.) Describe how you would design Google Docs from scratch 9 | 10 | ### Easy 11 | 12 | 1.) Add up the elements in an array: 13 | 14 | 2.) Given the radius of a circle, calculate the area. 15 | 16 | 3.) Find the Euclidean distance between two coordinate points. 17 | 18 | 4.) Find the Euclidean distance between 2 points in n dimensions. 19 | 20 | 5.) Add up the elements in an array: 21 | 22 | 6.) Write FizzBuzz. This is a function that prints out the numbers 1 to 100, 23 | and whenever a multiple of 3 is reached, print "fizz", when a multiple of 5 is 24 | reached, print "buzz", and whenever a number that is a multiple of both is 25 | reached print "fizzbuzz". 26 | 27 | 7.) Given two strings, check whether the first string is a substring of the 28 | second string. What is the runtime of your algorithm? 29 | 30 | 8.) Write a function to reverse a string 31 | 32 | ### Medium 33 | 34 | 1.) Given a two-dimensional array in which each row and each column is sorted, 35 | detect if a given element is in the array* 36 | 37 | 2.) Write a method that sorts a list of strings such that all anagrams are 38 | adjacent in the list 39 | 40 | 3.) Given an integer, return as a string the binary representation of the integer. 41 | 42 | 4.) Given a binary search tree, print out the elements in level order. 43 | for example, for the tree 44 | 8 45 | /\ 46 | 6 9 47 | /\ \ 48 | 5 7 11 49 | 50 | It will print 8 6 9 5 7 11 51 | 52 | 53 | 5.) Given a binary search tree, print out the elements in sorted order. 54 | 55 | 56 | 6.) Determine if two strings are a cipher match. Two strings are a cipher match 57 | if they have the same ordering of characters, even if the characters themselves 58 | are not the same. For example, "aabb" and "ccdd" are a cipher match, as are 59 | "abccd" and "efggh" 60 | 61 | 7.) In an array containing integers, one element is duplicated. Find this element. 62 | 63 | 8.) Write a function that finds the nth Fibonacci number. The Fibonacci numbers 64 | are a sequence of numbers where each number is the sum of the previous two 65 | numbers: 1,1,2,3,5,8,13.. 66 | 67 | 9.) Write a function that gives the number of possible ways one can combine 68 | quarters, dimes, and nickels to form n cents (0 is a possibility). 69 | 70 | 10.) Write a function that given a string detects whether all parentheses are 71 | matched 72 | 73 | 11.) Implement a data structure that supports the native operations of stack, 74 | push and pop, but also allow you to find the minimum in O(1) time. 75 | 76 | 12.) Given a list, return all permutations of the list* 77 | 78 | 13.) Given a list of numbers, return the powerset of this list. The powerset 79 | is the set of all subsets of the list. 80 | For example, the power set of [1,2,3] is 81 | [[],[1],[2],[3], [1,2], [2,3], [1,3], [1,2,3]] 82 | 83 | 14.) Given a list of strings, print out every string and its reverse if the reverse 84 | of the string is also in the list. 85 | 86 | 15.) What is the second largest element in a binary search tree? 87 | 88 | 16.) Write a function to sort a list of numbers. What is the runtime of the 89 | algorithm that you have written? Can it be improved? 90 | 91 | 17.) Given a list of numbers and a target number, find the number of ways the 92 | numbers in the list can add to the target number. Each number in the list can 93 | be reused. For example, if the list is [4,8,2,6] and the target number is 12, 94 | it can be formed with 95 | [2,6,4],[8,4],[6,6], [2,2,2,2,2,2], [8,2,2], [6,2,2,2], [4,4,4], [4,2,2,2,2] 96 | and the program should return 8. 97 | 98 | 18.) Find the maximum continuous subsequence of a list, and return its sum. 99 | This is the continous subsequence (adjacent elements) that has the largest sum. 100 | For example, for [7,-8,4,-1,5,-3,-2,6,1], the maximum continuous subsequence is 101 | [4,-1,5,-3,-2,6,1], which adds to 10. 102 | 103 | ### Hard 104 | 105 | 1.) Write a Brainf*ck interpreter. An interpreter is a program that accepts 106 | another program as input and executes it. Brainf*ck is a language consisting 107 | of characters "><+-[ ].,", where the program itself represents a large array 108 | of data. The command 109 | ">" moves a data pointer, which points at a given element, to the element on 110 | the right, the command "<" moves the data pointer to the element on the left, 111 | "+" increments the value of the element that the data pointer is pointed it, 112 | and "-" decrements it. "," takes raw input and puts it in the element that the 113 | data pointer is it, and "." outputs the value of the current element. The "]" 114 | cell that the data pointer is pointed is 0, then move the corresponding "[" character. 115 | 116 | 2.) Find the longest common substring between two strings. ie. for "abcde" and 117 | "acccde" the longest common substring is "acde". 118 | 119 | 3.) Write a maze-solver: Given a matrix of 1’s and 0’s, where a 1 indicates a 120 | position that you can move to and a 0 one that you cannot move to, a start 121 | coordinate, and an end coordinate, find the shortest path from the start 122 | coordinate to the end coordinate. 123 | 124 | 4.) Sort a linked list. 125 | 126 | 5.) Given a sudoku board, determine whether what has been placed on the board is 127 | a valid solution. Remember that each column must contain numbers 1-9, as must 128 | each row 129 | # ADI Interview Workshop Solutions 130 | 131 | ### Easy 132 | 133 | 1.) 134 | 135 | def array_sum(array): 136 | sum = 0 137 | for element in array: 138 | sum += element 139 | return sum 140 | 2.) 141 | 142 | def area(radius): 143 | math.pi * pow(r, 2) 144 | 145 | 146 | 3.) 147 | 148 | def distance(x1, x2, y1, y2): 149 | sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)) 150 | 4.) 151 | 152 | def distance(x,y): 153 | square_sum = 0 154 | for i in range(len(x)): 155 | square_sum += pow(x[i] - y[i], 2) 156 | return sqrt(square_sum) 157 | 158 | 5.) 159 | 160 | def array_sum(array): 161 | sum = 0 162 | for element in array: 163 | sum += element 164 | return sum 165 | 166 | 6.) 167 | 168 | def fizzbuzz(): 169 | for i in range(100): 170 | if i % 15 == 0: 171 | print "hello" 172 | elif i % 5 == 0: 173 | print "buzz" 174 | elif i % 3 == 0: 175 | print "fizz" 176 | else: 177 | print i 178 | 7.) 179 | 180 | def substring(str1, str2): 181 | is_substring = False 182 | for i in range(len(str2)): 183 | is_match = True 184 | for j in range(len(str1)): 185 | if str2[i + j] != str1[j]: 186 | is_match = False 187 | if is_match: 188 | return True 189 | return False 190 | 191 | 8.) 192 | 193 | def reverse(str): 194 | reversed_string = "" 195 | for i in range(len(str), 0, -1): 196 | reversed_string += str[i] 197 | return reversed_string 198 | 199 | ### Medium 200 | 201 | 1.) 202 | 203 | Hint: How would you do it if it were one dimensional? 204 | 205 | Naive Solution: Do a binary search on each row. This has an O(nlog(m)) runtime. 206 | 207 | Proper Solution: Use binary search across rows as well, giving a runtime of 208 | O(log(m) * log(n)), where m and n are the numbers of rows and columns 209 | 210 | 2.) Hint: Do we need to do a sorting algorithm at all? How do you tell if two 211 | strings are anagrams? 212 | 213 | A Solution: sort each individual string by its letters, and then store the 214 | sorted string in a dictionary that maps the sorted string to a list of indices. 215 | These indices represent the position of elements in the array that when sorted 216 | are the sorted string inserted in the dictionary. 217 | 218 | Once you have gone through the whole array, iterate over the dictionary and 219 | for each item, make swaps in the array such that elements in the each of the 220 | indices in the list are adjacent. 221 | 222 | 3.) Hint: What happens when you try to do this by hand? 223 | Hint: What if you try it with a power of 2? 224 | 225 | Solution: Greedily pick the biggest power of 2 that works, set that bit to 1, 226 | subtract that power of 2 from the decimal number, and then pick the biggest 227 | power of 2 that fits into that. Keep going until finished. 228 | 229 | 4.) Hint: Think about what data structures might make sense here. 230 | 231 | Solution: Recursively add elements of the BST to a queue, and then dequeue 232 | the elements 233 | 234 | 5.) Solution: Recurse through the tree, printing out the element on the left, 235 | then the parent element, then the element on the right. 236 | 237 | 6.) Hint: What exactly about the strings are you comparing? 238 | 239 | def cipher_match(str1, str2): 240 | return string_to_cipher(str1) == string_to_cipher(str2) 241 | 242 | def string_to_cipher(str): 243 | used_chars = {} 244 | cipher = "" 245 | character_count = 0 246 | for c in str: 247 | dict_entry = used_chars.get(c) 248 | if dict_entry: 249 | cipher += dict_entry 250 | else: 251 | used_chars[c] = character_count 252 | character_count += 1 253 | return cipher 254 | 255 | 7.) 256 | def find_duplicate(list): 257 | element_dict = {} 258 | for element in list: 259 | if element in element_dict: 260 | return element 261 | else: 262 | element_dict[element] = 1 263 | 264 | 8.) 265 | def fib(n): 266 | current =1 267 | previous = 1 268 | for i in range(n-2): 269 | updated_previous = current 270 | current = previous + current 271 | previous = updated_previous 272 | return current 273 | 274 | 9.) Hint: How would you try all possibilities? 275 | 276 | @memoize 277 | def count_change(n): 278 | if n == 0: 279 | return 1 280 | 281 | if n < 5: 282 | return 0 283 | elif n < 10: 284 | return count_change(n - 5) 285 | elif n < 25: 286 | return count_change(n-5) + count_change(n - 10) 287 | else: 288 | return count_change(n - 25) + count_change(n - 10) + count_change(n - 5) 289 | 290 | 10.) Hint: What data structures might be helpful? 291 | 292 | Solution: Use a stack, and make sure the stack is empty when the program 293 | is complete. 294 | 295 | 11.) Solution: Use two stacks, one to keep track of the current minimum, and 296 | one to keep track of the order that the elements came in. The second stack 297 | is used when push and pop operations happen, and when an element is pushed 298 | that is lower than the current min, add it to the current min stack, and when 299 | that element is popped, if it is the current min, pop it from the stack. 300 | 301 | 12.) Solution: recursively iterate through the string, keeping track of a list 302 | of characters that you have already use. 303 | 304 | 13.) 305 | 306 | Hint: How many elements are in the power set of a list? 307 | 308 | 309 | def power_set(list): 310 | power_set_helper(list, [], []) 311 | 312 | # This can be done is a pure fashion I think...exercise to the reader 313 | # if you care. 314 | 315 | def power_set_helper(remaining_list, current_list, power_set): 316 | if not remaining_list: 317 | power_set.append(current_list) 318 | else 319 | power_set_helper(remaining_list[1:], current_list, power_set) 320 | power_set_helper(remaining_list[1:], current_list.append(remaining_list[0]), power_set) 321 | return power_set 322 | 323 | 324 | 14.) Hint: What kind of data structure might you need to keep in place to 325 | store information that you need? 326 | 327 | def print_reverse(string_list): 328 | dict = {} 329 | for str in string_list: 330 | if dict[str]: 331 | print str 332 | print ''.join(reversed(str)) 333 | else: 334 | dict[''.join(reversed(str))] = 1 335 | 336 | 15.) 337 | Hint: Try drawing out a tree. 338 | 339 | If the largest element of the tree has a lesser child, then that is the 340 | second largest element, otherwise, it is the parent of the largest element. 341 | 342 | 16.) 343 | 344 | def sort(ls): 345 | for i in range(len(ls)): 346 | for j in range(i-1,0, -1): 347 | if list[j] > list[j-1]: 348 | tmp = list[j] 349 | list[j] = list[j-1] 350 | list[j-1] = tml 351 | 352 | 17.) Hint: Could building a set of numbers be structured conceptually as a tree? 353 | 354 | Solution: 355 | 356 | def meet_target(list, target): 357 | meet_target_helper(list, target, 0) 358 | 359 | def meet_target_helper(remaining_list, target, current_sum): 360 | if current_sum == target: 361 | return 1 362 | elif current_sum > target: 363 | return 0 364 | elif len(remaining_list) == 0: 365 | return 0 366 | else: 367 | return meet_target_helper(remaining_list, target, current_sum + remaining_list[0]) + 368 | meet_target_helper(remaining_list[1:], target, current_sum) 369 | 370 | 18.) Hint: Why don't you start by trying to enumerate all the continuous 371 | subsequences? What extra work are you doing? Try solving it by hand for 372 | a given sequence 373 | 374 | Naive: Try enumerating all subsequences and check the longest one. How many 375 | are there? 376 | 377 | Better Solution: 378 | 379 | def longest_continuous_subsequence(list): 380 | current_sum = 0 381 | larget_sum = 0 382 | 383 | for i in list: 384 | current_sum += i 385 | if current_sum > largest_sum: 386 | largest_sum = current_sum 387 | elif current_sum < 0: 388 | current_sum = 0 389 | 390 | ### Hard 391 | 392 | 1.) Use an array to keep track of your data, store a "program counter" as an 393 | integer to keep track of where you are in the program, and a "data counter" to 394 | keep track of what array element you are currently operating on. Then, use a case/switch 395 | statement to parse out commands. For ">" and "<" operations, move the data 396 | counter accordingly, for "+" and "-" operations, change the data accordingly, 397 | and for "[" and "]" change the program counter accordingly. 398 | 399 | 2 and 3.) Both require dynamic programming solutions 400 | 401 | 4.) Tedious programming--mergesort is probably the best solution here although 402 | I think insertion sort is good enough. 403 | 404 | 5.) This is just tedious programming, the brute force solution is good enough. 405 | -------------------------------------------------------------------------------- /medium/2d_array.py: -------------------------------------------------------------------------------- 1 | # Given a two-dimensional array in which each row and each column is sorted, 2 | # detect if a given element is in the array 3 | -------------------------------------------------------------------------------- /medium/anagrams.py: -------------------------------------------------------------------------------- 1 | # Write a method that sorts a list of strings such that all anagrams are 2 | # adjacent in the list 3 | -------------------------------------------------------------------------------- /medium/binary_representation.py: -------------------------------------------------------------------------------- 1 | # Given an integer, return as a string the binary representation of the integer. 2 | -------------------------------------------------------------------------------- /medium/bst_level_order.py: -------------------------------------------------------------------------------- 1 | # Given a binary search tree, print out the elements in level order. 2 | # for example, for the tree 3 | 4 | # 8 5 | # /\ 6 | # 6 9 7 | # /\ \ 8 | # 5 7 11 9 | # 10 | # It will print 8 6 9 5 7 11 11 | # 12 | # 13 | # 14 | -------------------------------------------------------------------------------- /medium/bst_sorted_order.py: -------------------------------------------------------------------------------- 1 | # Given a binary search tree, print out the elements in sorted order. 2 | -------------------------------------------------------------------------------- /medium/cipher_match.py: -------------------------------------------------------------------------------- 1 | # Determine if two strings are a cipher match. Two strings are a cipher match 2 | # if they have the same ordering of characters, even if the characters themselves 3 | # are not the same. For example, “aabb” and “ccdd” are a cipher match, as are 4 | # “abccd” and “efggh” 5 | 6 | def cipher_match(str1, str2): 7 | return string_to_cipher(str1) == string_to_cipher(str2) 8 | 9 | def string_to_cipher(str): 10 | used_chars = {} 11 | cipher = "" 12 | character_count = 0 13 | for c in str: 14 | dict_entry = used_chars.get(c) 15 | if dict_entry: 16 | cipher += dict_entry 17 | else: 18 | used_chars[c] = character_count 19 | character_count += 1 20 | return cipher 21 | -------------------------------------------------------------------------------- /medium/duplicate.py: -------------------------------------------------------------------------------- 1 | # In an array containing integers, one element is duplicated. Find this element. 2 | # What is the performance of your algorithm? How much memory does it use? 3 | 4 | def find_duplicate(list): 5 | element_dict = {} 6 | for element in list: 7 | if element in element_dict: 8 | return element 9 | else: 10 | element_dict[element] = 1 11 | -------------------------------------------------------------------------------- /medium/fib.py: -------------------------------------------------------------------------------- 1 | # Write a function that finds the nth Fibonacci number. The Fibonacci numbers 2 | # are a sequence of numbers where each number is the sum of the previous two 3 | # numbers: 1,1,2,3,5,8,13.. 4 | 5 | def fib(n): 6 | current =1 7 | previous = 1 8 | for i in range(n-2): 9 | updated_previous = current 10 | current = previous + current 11 | previous = updated_previous 12 | return current 13 | -------------------------------------------------------------------------------- /medium/make_change.py: -------------------------------------------------------------------------------- 1 | # Write a function that gives the number of possible ways one can combine 2 | # quarters, dimes, and nickels to form n cents. 3 | -------------------------------------------------------------------------------- /medium/matching_parentheses.py: -------------------------------------------------------------------------------- 1 | # Write a function that given a string detects whether all parentheses are 2 | # matched 3 | -------------------------------------------------------------------------------- /medium/min_stack.py: -------------------------------------------------------------------------------- 1 | # Implement a data structure that supports the native operations of stack, 2 | # push and pop, but also allow you to find the minimum in O(1) time. 3 | 4 | # Solution is to under the hood maintain 2 stacks, one is the actual stack, and 5 | # the other keeps the current minimum, and when the current minimum is popped 6 | # off the stack, pop it off the stack 7 | -------------------------------------------------------------------------------- /medium/permutations.py: -------------------------------------------------------------------------------- 1 | # Given a list, return all permutations of the list 2 | -------------------------------------------------------------------------------- /medium/powerset.py: -------------------------------------------------------------------------------- 1 | # Given a list of numbers, return the powerset of this list. The powerset 2 | # is the set of all subsets of the list. 3 | # For example, the power set of [1,2,3] is 4 | # [[],[1],[2],[3], [1,2], [2,3], [1,3], [1,2,3]] 5 | -------------------------------------------------------------------------------- /medium/print_reverse.py: -------------------------------------------------------------------------------- 1 | # Given a list of strings, print out every string and its reverse if the reverse 2 | # of the string is also in the list. 3 | 4 | def print_reverse(string_list): 5 | dict = {} 6 | for str in string_list: 7 | if dict[str]: 8 | print str 9 | print ''.join(reversed(str)) 10 | dict[''.join(reversed(str))] = 1 11 | 12 | -------------------------------------------------------------------------------- /medium/second_largest_bst.py: -------------------------------------------------------------------------------- 1 | # What is the second largest element in a binary search tree? 2 | -------------------------------------------------------------------------------- /medium/sort.py: -------------------------------------------------------------------------------- 1 | # Write a function to sort a list of numbers. What is the runtime of the 2 | # algorithm that you have written? Can it be improved? 3 | 4 | 5 | # This is insertion sort, it is acceptable answer for this question but not 6 | # in many real-world circumstances. 7 | def sort(ls): 8 | for i in range(len(ls)): 9 | for j in range(i-1,0, -1): 10 | if list[j] > list[j-1]: 11 | tmp = list[j] 12 | list[j] = list[j-1] 13 | list[j-1] = tml 14 | -------------------------------------------------------------------------------- /medium/target.py: -------------------------------------------------------------------------------- 1 | # Given a list of numbers and a target number, find the number of ways the 2 | # numbers in the list can add to the target number. 3 | -------------------------------------------------------------------------------- /systems/systems_questions.md: -------------------------------------------------------------------------------- 1 | These questions examine your knowledge of systems programming, operating 2 | systems, and computer architecture. They should be useful when interviewing 3 | for positions that will require writing low-level code. 4 | 5 | # Memory Management 6 | 7 | ## Question 1 8 | 9 | What does the following C code do? 10 | 11 | int main(void) { 12 | int *x = NULL; 13 | int y = *x; 14 | } 15 | 16 | Explain in as much detail as possible what happens in the processor, 17 | OS kernel, and userspace when this code is executed. 18 | 19 | ## Question 2 20 | 21 | Two separate Linux processes attempt to access memory at the same address, 22 | will these processes interfere with each other? Why or why not? 23 | 24 | ## Question 3 25 | 26 | Explain in as much detail as possible how modern operating systems handle 27 | getting requests for more memory than is available on the machine. 28 | 29 | ## Question 4 30 | 31 | Given the following two programs which are equivalent in functionality, 32 | which one do you expect to run faster and why? 33 | 34 | for (i = 0; i < N; i++) { 35 | for (j = 0; j < M; j++) { 36 | sum += arr[i]; 37 | } 38 | } 39 | 40 | for (j = 0; j < M; j++) { 41 | for (i = 0; i < N; i++) { 42 | sum += arr[i]; 43 | } 44 | } 45 | 46 | # Synchronization 47 | 48 | ## Question 1 49 | 50 | Compare-and-swap is an atomic operation supplied by many CPUs to allow 51 | implementation of more complex synchronization primitives. 52 | Compare-and-swap takes a memory region to be updated, the expected value 53 | of that region, and a new value. It will atomically examine the current 54 | contents of memory and, if it is the same as the expected value, update 55 | the memory region with the new value. It then returns the value that was 56 | read from memory. 57 | 58 | The following C-like pseudocode explains what compare-and-swap does. 59 | 60 | int compare_and_swap(int *p, int oldval, int newval) 61 | { 62 | int curval = *p; 63 | if (curval == oldval) { 64 | *p = newval; 65 | } 66 | return curval; 67 | } 68 | 69 | Using the compare-and-swap function, please explain how you would implement 70 | a basic `lock` and `unlock` function. The `lock` function takes an integer 71 | pointer (the lock object) can be called from any number of threads. 72 | Only one thread should be allowed to progress past the lock function at 73 | a time. The thread will hold the lock until it calls `unlock` to release it. 74 | So, for instance, I would expect the following code to work as expected 75 | without race conditions when it is run using multiple threads. 76 | 77 | lock(lck); 78 | /* --- critical section --- */ 79 | unlock(lck); 80 | 81 | ## Question 2 82 | 83 | Given a working `lock` and `unlock` function, explain what the problem is 84 | with the following multi-threaded code and how you would correct it. 85 | 86 | In thread A 87 | 88 | lock(lckA); 89 | lock(lckB); 90 | /* --- critical section --- */ 91 | unlock(lckA); 92 | unlock(lckB); 93 | 94 | In thread B 95 | 96 | lock(lckB); 97 | lock(lckA); 98 | /* --- critical section --- */ 99 | unlock(lckA); 100 | unlock(lckB); 101 | 102 | ## Question 3 103 | 104 | Explain what a semaphore is and how you would implement it using our 105 | `lock` and `unlock` functions. 106 | --------------------------------------------------------------------------------