Concepts and Examples with Python
An online retailer has about 10 million products in their catalog. However, they estimate about 10 percent of these are duplicate listings that they would like to remove. How would you do this?
A fast food restaurant wants to determine which factors lead to the longest wait times. You have access to a years worth of high quality camera footage in their restaurant from many angles. How would you solve this problem?
Bonus: They also want to determine which factors make it more likely for a customer to leave the line and not come back.
Notation | Name | Examples |
---|---|---|
\(O(1)\) | Constant | \[100 = O(1),\\ 1 = O(x) \] |
\(O(\log x)\) | Logarithmic | \[2 \log(x^2) = \Theta(\log x),\\ \frac{1}{10^{10}} \log(x) = O(\log x),\\ \log(\log(x)) = O(\log(x))\] |
\(O(x)\) | Linear | \[20x + 10 = \Theta(x),\\ \log(x) = O(x)\] |
\(O(x \log x)\) | Loglinear | \[x \log(x^3) = \Theta(x\log x), \\ x \log x = \Omega(\log x)\] |
\(O(x^2)\) | Quadratic | \[x^2 + 1000x = \Theta(x^2)\] |
\(O(2^x)\) | Exponential | \[x^{1000} = O(2^x), \\ 2^x = O(n!)\] |
What is the runtime and space complexity to find the sum of a list of integers of length \(n\)?
What is the runtime and space complexity to find all the cumulative sums of a list of integers of length \(n\)?
What is the runtime and space complexity to find the count of occurrences of each number in a list of length \(n\)?
What is the runtime and space complexity to determine if a word is in the English dictionary?
Two words “interlock” if taking alternative letters from each forms a new word. For example, “shoe” and “cold” interlock to form “schooled”. Given a list of words, find all pairs of words that interlock. If \(n\) is the number of words and \(k\) is the maximum length of a word, what are the complexities?
# Assume word 1 is the longer of the words
def interlock(word1, word2):
size_diff = len(word1) - len(word2)
if size_diff not in (0, 1):
return ""
interlocked = ""
if size_diff > 0:
interlocked += word1[0]
word1 = word1[1:]
for letter, index in enumerate(word1, word2):
interlocked += letter + word2[index]
return interlocked
# How does this change if words is a set
# instead of a list?
def all_interlocks(words):
interlocking = []
for word1 in words:
for word2 in words:
if interlock(word1, word2) in words:
interlocking.append((word1, word2))
return interlocking
Two words “interlock” if taking alternative letters from each forms a new word. For example, “shoe” and “cold” interlock to form “schooled”. Given a list of words, find all pairs of words that interlock. If \(n\) is the number of words and \(k\) is the maximum length of a word, what are the complexities?
def deinterlock(word):
flip_flop = True
first_word = ""
second_word = ""
for letter in word:
if flip_flop:
first_word += letter
else:
second_word += letter
flip_flop = not flip_flop
return first_word, second_word
def all_interlocks(words):
as_set = set(words)
interlocking = []
for word in words:
word1, word2 = deinterlock(word)
if word1 in as_set and word2 in as_set:
inlocking.append((word1, word2))
return interlocking
Data Structures are simply objects that store data. Depending on how data is stored, various operations will take different amounts of time. The most standard operations are:
Python Lists are also (almost) Arrays
Python Lists are also stacks
append_times = []
insert_times = []
for list_ in my_lists:
append_times.append(
sum(timeit.repeat(
"list_copy.append(-1)",
setup="list_copy = list(list_)",
repeat=TRIALS,
number=100,
globals=globals()))/TRIALS)
insert_times.append(
sum(timeit.repeat(
"list_copy.insert(90, -1)",
setup="list_copy = list(list_)",
repeat=TRIALS,
number=100,
globals=globals()))/TRIALS)
delete_times = []
pop_times = []
for list_ in my_lists:
delete_times.append(
sum(timeit.repeat(
"del list_copy[10]",
setup="list_copy = list(list_)",
repeat=TRIALS,
number=80,
globals=globals()))/TRIALS)
pop_times.append(
sum(timeit.repeat(
"list_copy.pop()",
setup="list_copy = list(list_)",
repeat=TRIALS,
number=100,
globals=globals()))/TRIALS)
Sets have limited functionality! We can add, delete, and search elements in constant time, but cannot maintain any indexing or ordering.
Remember, Dictionaries are just sets that associate the keys to values!
Linked Lists are not native to Python, but they are one of the most basic data structures that you may see often in technical interviews. Try to determine the runtime complexities of the 4 basic operations of a Linked List. Read the code below to get an idea of how they are structured. Hint: Draw a picture.
class Node:
def __init__(self, value):
self.value = value
self.next_node = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def add_item_at_end(value):
if self.head is None:
self.head = Node(value)
self.tail = self.head
elif self.tail is not None:
new_node = Node(value)
self.tail.next_node = new_node
self.tail = new_node
# ... and so on
The DNA sequence is composed of a series of nucleotides abbreviated as 'A'
, 'C'
, 'G'
, and 'T'
.
For example, "ACGAATTCCG"
is a DNA sequence. When studying DNA, it is useful to identify repeated sequences within the DNA.
Given a string s that represents a DNA sequence, return all the 10
-letter-long sequences (substrings) that occur more than once in a DNA molecule. You may return the answer in any order.
Example 1:
Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
Output: ["AAAAACCCCC","CCCCCAAAAA"]
Example 2:
Input: s = "AAAAAAAAAAAAA"
Output: ["AAAAAAAAAA"]
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:
Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:
Input: nums = [3,3], target = 6
Output: [0,1]
Given two integer arrays nums1
and nums2
, return an array of their intersection. Each element in the result must be unique and you may return the result in any order.
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]
Example 2:
Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [9,4]
Explanation: [4,9] is also accepted.
Given two integer arrays nums1
and nums2
, return an array of their intersection. Each element in the result must appear as many times as it shows in both arrays and you may return the result in any order.
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
Example 2:
Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [4,9]
Explanation: [9,4] is also accepted.
In summary: Pick a field/discipline you are most interested in, find some listings that talk about qualifications, and study relevant resources for passing the interviews. If you want to focus on it now, you can, but certainly do not have to. You can do an internship after your 2nd year!