├── .gitignore
├── Problem 1-30
├── problem_10.py
├── problem_11_autocompletion.py
├── problem_12.py
├── problem_13.py
├── problem_14.py
├── problem_15.py
├── problem_16.py
├── problem_17.py
├── problem_18.py
├── problem_19.py
├── problem_1_two_sum.py
├── problem_2.py
├── problem_20.py
├── problem_21.py
├── problem_22.py
├── problem_23.py
├── problem_24.py
├── problem_25_regular_expression_matching.py
├── problem_26.py
├── problem_27.py
├── problem_28.py
├── problem_29.py
├── problem_30.py
├── problem_3_serializer.py
├── problem_4.py
├── problem_5.py
├── problem_6.py
├── problem_7.py
├── problem_8.py
└── problem_9.py
├── Problem 31-60
├── problem_31.py
├── problem_32.py
├── problem_33.py
├── problem_34.py
├── problem_35.py
└── problem_36.py
├── Problem Descriptions.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_10.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Apple.
3 |
4 | Implement a job scheduler which takes in a function f and an integer n, and
5 | calls f after n milliseconds.
6 | '''
7 |
8 | '''
9 | EdgeCases:
10 | * Imagine a case, where (A,10) task A is scheduled to run after 10 seconds
11 | * and then when at 3rd second, another task B comes where (B,2) seconds
12 | * then which one would be executed first ?
13 |
14 | A more sophisticated edge case is, if two items receive the same absolute time,
15 | is it required to maintain order of insertion when running? Might be relevant
16 | in some use cases. The mentioned edge case, is obvious. at 5 task B runs, at 10
17 | task A runs.
18 | '''
19 |
20 | '''
21 | Solution:
22 | 1) calculate absolute times when a task get's added
23 | 2) push it into a priority queue with smallest absolute on top (binary heap)
24 | 3) have a runner that polls the queue once in a time interval (e.g. second) and
25 | checks if top task is to be executed, pop items from the heap that need to
26 | be executed.
27 | 4) now, the question is, how long does the run take? can I execute it
28 | synchronously or will this delay the scheduler? I could as well span into a
29 | thread pool to call run there.
30 |
31 | Also refer to following URL:
32 | https://pymotw.com/3/sched/
33 | '''
34 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_11_autocompletion.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Twitter.
3 |
4 | Implement an autocomplete system. That is, given a query string s and a set of
5 | all possible query strings, return all strings in the set that have s as a prefix.
6 |
7 | For example, given the query string de and the set of strings [dog, deer, deal],
8 | return [deer, deal].
9 |
10 | Hint: Try preprocessing the dictionary into a more efficient data structure to
11 | speed up queries.
12 | '''
13 | from collections import defaultdict
14 |
15 | class Trie_Node(object):
16 | def __init__(self, char=None):
17 | self.char = char
18 | self.children = defaultdict(Trie_Node)
19 | self.end_of_word = False
20 |
21 |
22 | def add(trie_root, word):
23 | cur_node = trie_root
24 | for char in word:
25 | if char in cur_node.children:
26 | cur_node = cur_node.children[char]
27 | else:
28 | new_node = Trie_Node(char)
29 | cur_node.children[char] = new_node
30 | cur_node = new_node
31 | cur_node.end_of_word = True
32 |
33 |
34 | def search(trie_root, pattern):
35 | '''
36 | Args:
37 | trie_root(Trie_Node): the root of the Trie tree
38 | pattern(string): the query string for autocomplete
39 | Returns:
40 | list: a list of possible results
41 | '''
42 | cur_node = trie_root
43 | res = list()
44 | for char in pattern:
45 | if char in cur_node.children: # able to auto-complete
46 | cur_node = cur_node.children[char]
47 | res.append(char)
48 | else: # no matching
49 | return []
50 |
51 | prefix = ''.join(res[:-1])
52 | suffix = build_str(cur_node) # recursively find the suffix
53 | return [prefix + item for item in suffix]
54 |
55 |
56 | def build_str(trie_node):
57 | '''
58 | Args:
59 | trie_node(Trie_Node): the node in the Trie that deeper than the pattern
60 | Returns:
61 | list: a list of sub_string of possible suffix
62 | '''
63 | if trie_node.end_of_word:
64 | return [trie_node.char]
65 |
66 | sub_string = []
67 | for k, v in trie_node.children.items():
68 | sub_string.extend(build_str(v))
69 |
70 | sub_string = [trie_node.char + item for item in sub_string]
71 | return sub_string
72 |
73 |
74 | def main():
75 | root = Trie_Node('*')
76 | str_list = ['dog', 'deer', 'deel', 'deat', 'dealete', 'deassase']
77 | for word in str_list:
78 | add(root, word)
79 | print search(root, 'de')
80 |
81 |
82 | if __name__ == '__main__':
83 | main()
84 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_12.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Amazon.
3 |
4 | There exists a staircase with N steps, and you can climb up either 1 or 2 steps
5 | at a time. Given N, write a function that returns the number of unique ways you
6 | can climb the staircase. The order of the steps matters.
7 |
8 | For example, if N is 4, then there are 5 unique ways:
9 |
10 | 1, 1, 1, 1
11 | 2, 1, 1
12 | 1, 2, 1
13 | 1, 1, 2
14 | 2, 2
15 |
16 | What if, instead of being able to climb 1 or 2 steps at a time, you could climb
17 | any number from a set of positive integers X? For example, if X = {1, 3, 5}, you
18 | could climb 1, 3, or 5 steps at a time.
19 | '''
20 | def cache(func):
21 | data = dict()
22 | def wrapper(N, X):
23 | if N in data:
24 | return data[N]
25 | else:
26 | data[N] = func(N, X)
27 | return data[N]
28 | return wrapper
29 |
30 |
31 | @cache
32 | def climb_up(N, X):
33 | '''
34 | Dynamic Programming
35 | Args:
36 | N(int): a staircase with N steps
37 | X(list): steps that are allowed
38 | Returns:
39 | int: number of ways to get to the top of the staircase
40 | '''
41 | if N <= 1:
42 | return 1
43 |
44 | num_ways = 0
45 | for step in X:
46 | if N >= step:
47 | num_ways += climb_up(N - step, X)
48 | return num_ways
49 |
50 |
51 | def main():
52 | print climb_up(100, [1, 3, 5])
53 |
54 | if __name__ == '__main__':
55 | main()
56 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_13.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Amazon.
3 |
4 | Given an integer k and a string s, find the length of the longest substring that
5 | contains at most k distinct characters.
6 |
7 | For example, given s = "abcba" and k = 2, the longest substring with k distinct
8 | characters is "bcb".
9 | '''
10 |
11 | def solution(string, k):
12 | '''
13 | Keep a window and add elements to the window till it contains less or equal
14 | k. If unique elements exceeds than required in window, start removing the
15 | elements from left side.
16 |
17 | Args:
18 | string(string)
19 | k(int)
20 | Returns:
21 | int: count of the length of the longest substring
22 | '''
23 | table = dict()
24 | slow = -1
25 | fast = -1
26 | distinct_cnt = 0
27 | for idx, char in enumerate(string): # iter over every char
28 | if char in table: # hit in the table
29 | table[char] += 1
30 | fast = idx
31 | else: # miss, means this is a new distinct char
32 | if len(table) == k: # the table is full, have to move from left
33 | while len(table) != k - 1:
34 | slow += 1
35 | char_slow = string[slow]
36 | table[char_slow] -= 1
37 | if table[char_slow] == 0:
38 | table.pop(char_slow)
39 | table[char] = 1
40 | fast = idx
41 | else: # table is not full, directly add it in
42 | table[char] = 1
43 | fast = idx
44 | if fast - slow > distinct_cnt:
45 | distinct_cnt = fast - slow
46 | return distinct_cnt
47 |
48 |
49 | def solution2(s, k):
50 | '''
51 | Thanks to Ricardo:
52 | https://github.com/r1cc4rdo/daily_coding_problem/blob/master/daily_coding_problem_11_15.py
53 | providing this wonderful concise solution.
54 | '''
55 | assert(len(s) >= k)
56 |
57 | start_index, end_index, max_length = 0, k, k
58 | while end_index < len(s):
59 |
60 | end_index += 1
61 | while True:
62 |
63 | distinct_characters = len(set(s[start_index:end_index]))
64 | if distinct_characters <= k:
65 | break
66 |
67 | start_index += 1
68 |
69 | max_length = max(max_length, end_index - start_index)
70 |
71 | return max_length
72 |
73 | def main():
74 | s = 'aabbcc'
75 | k = 3
76 | print solution2(s, k)
77 |
78 | if __name__ == '__main__':
79 | main()
80 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_14.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | '''
3 | This problem was asked by Google.
4 |
5 | The area of a circle is defined as πr^2. Estimate π to 3 decimal places using a
6 | Monte Carlo method.
7 |
8 | Hint: The basic equation of a circle is x2 + y2 = r2.
9 | '''
10 | import random
11 | import math
12 |
13 | random.seed(0xBADC0FFE)
14 |
15 | def est_pi(num):
16 | cnt = 0
17 | total = 0
18 | prev_pi, pi_approx = 0, 3
19 |
20 | while True:
21 | point = list()
22 | for i in range(num):
23 | point.append((random.random(), random.random()))
24 | if point[i][0] ** 2 + point[i][1] ** 2 <= 1:
25 | cnt += 1
26 | total += 1
27 | prev_pi = pi_approx
28 | pi_approx = 4 * cnt / float(total)
29 | print 'prev_pi = {}, pi_approx = {}'.format(prev_pi, pi_approx)
30 | if abs(prev_pi - pi_approx) < 1e-9: # assume we don't know math.pi
31 | return pi_approx
32 | # if abs(math.pi - pi_approx) < 1e-4: # assume math.pi is known
33 | # return pi_approx
34 |
35 |
36 | def main():
37 | print est_pi(1000)
38 |
39 |
40 | if __name__ == '__main__':
41 | main()
42 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_15.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Facebook.
3 |
4 | Given a stream of elements too large to store in memory, pick a random element
5 | from the stream with uniform probability.
6 | '''
7 | '''
8 | Note:
9 |
10 | Let the current element's index be i.
11 |
12 | Choose to 'remember' the current element at probability 1/i. When EOF is reached,
13 | produced the element you remember.
14 |
15 | At the end, for each element with index i there is a probability to be chosen:
16 |
17 | https://stackoverflow.com/questions/23351918/select-an-element-from-a-stream-with-uniform-distributed-probability
18 |
19 | A formal prove can be done using induction, following these guidelines.
20 | '''
21 | import random
22 | random.seed(0xBADC0FFE)
23 |
24 | def sample_gen_func(num):
25 | for x in xrange(num):
26 | yield x
27 |
28 | def solution(sample_generator):
29 | sample_count = 0
30 | selected_sample = None
31 |
32 | for sample in sample_generator:
33 | sample_count += 1
34 | if random.random() <= 1.0 / sample_count:
35 | selected_sample = sample
36 |
37 | return selected_sample
38 |
39 | def main():
40 | num = 1000
41 | print solution(sample_gen_func(num))
42 |
43 | if __name__ == '__main__':
44 | main()
45 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_16.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Twitter.
3 |
4 | You run an e-commerce website and want to record the last N order ids in a log.
5 | Implement a data structure to accomplish this, with the following API:
6 |
7 | record(order_id): adds the order_id to the log
8 | get_last(i): gets the ith last element from the log. i is guaranteed to be
9 | smaller than or equal to N.
10 |
11 | You should be as efficient with time and space as possible.
12 | '''
13 | class OrdersLog(object):
14 | def __init__(self, num):
15 | self.circular_buffer = [None] * num
16 | self.current_index = 0
17 |
18 | def record(self, order_id):
19 | self.circular_buffer[self.current_index] = order_id
20 | self.current_index += 1
21 | if self.current_index == len(self.circular_buffer):
22 | self.current_index = 0
23 |
24 | def get_last(self, num):
25 | start_index = self.current_index - num
26 | if start_index < 0: # wrap around
27 | return (self.circular_buffer[start_index:] +
28 | self.circular_buffer[:self.current_index])
29 | else: # no wrapping required
30 | return self.circular_buffer[start_index:self.current_index]
31 |
32 |
33 | def main():
34 | N = 20
35 | log = OrdersLog(10)
36 | for id in xrange(35):
37 | log.record(id)
38 |
39 | assert(log.get_last(0) == [])
40 | assert(log.get_last(1) == [34])
41 | assert(log.get_last(5) == range(30, 35))
42 |
43 | if __name__ == '__main__':
44 | main()
45 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_17.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Suppose we represent our file system by a string in the following manner:
5 |
6 | The string "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" represents:
7 |
8 | dir
9 | subdir1
10 | subdir2
11 | file.ext
12 | The directory dir contains an empty sub-directory subdir1 and a sub-directory
13 | subdir2 containing a file file.ext.
14 |
15 | The string "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" represents:
16 |
17 | dir
18 | subdir1
19 | file1.ext
20 | subsubdir1
21 | subdir2
22 | subsubdir2
23 | file2.ext
24 | The directory dir contains two sub-directories subdir1 and subdir2. subdir1
25 | contains a file file1.ext and an empty second-level sub-directory subsubdir1.
26 | subdir2 contains a second-level sub-directory subsubdir2 containing a file
27 | file2.ext.
28 |
29 | We are interested in finding the longest (number of characters) absolute path
30 | to a file within our file system. For example, in the second example above,
31 | the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length
32 | is 32 (not including the double quotes).
33 |
34 | Given a string representing the file system in the above format, return the
35 | length of the longest absolute path to a file in the abstracted file system.
36 | If there is no file in the system, return 0.
37 |
38 | Note:
39 |
40 | The name of a file contains at least a period and an extension.
41 |
42 | The name of a directory or sub-directory will not contain a period.
43 | '''
44 |
45 | class Node(object):
46 | '''
47 | Node of a Directory N-ary Tree
48 | '''
49 | def __init__(self, val=None, level=None, parent=None, is_file=False):
50 | self.val = val
51 | self.level = level
52 | self.parent = parent
53 | self.subdir = list() # Node's children as a list
54 | self.is_file =is_file
55 |
56 | def add_node(self, node=None):
57 | self.subdir.append(node)
58 |
59 | def get_parent(self):
60 | return self.parent
61 |
62 |
63 | class Tree(object):
64 | '''
65 | A Directory N-ary Tree
66 | '''
67 | def __init__(self, root=None):
68 | self.root = Node('*', -1)
69 |
70 |
71 | def build_tree(path_str):
72 | '''
73 | Build a directory n-ary tree
74 | Args:
75 | path_str(string): a string represented a fild system path
76 | Returns:
77 | Tree: a directory tree
78 | '''
79 | path_dir = path_str.split('\n')
80 | dir_tree = Tree()
81 | cur_level = -1
82 | cur_root = dir_tree.root
83 |
84 | for token in path_dir:
85 | tabs = 0
86 | while token[tabs] == '\t':
87 | tabs += 1
88 |
89 | if cur_level >= tabs: # need to back track the parent node
90 | i = cur_level - tabs + 1
91 | while i != 0:
92 | cur_root = cur_root.get_parent()
93 | i -= 1
94 |
95 | if len(token.split('.')) > 1: # is a file
96 | new_node = Node(token[tabs:], tabs, cur_root, True)
97 | else: # not a file
98 | new_node = Node(token[tabs:], tabs, cur_root)
99 |
100 | cur_root.add_node(new_node)
101 | cur_level = tabs
102 | cur_root = new_node
103 |
104 | return dir_tree
105 |
106 |
107 | def lgst_file_path(node):
108 | '''
109 | Given a tree node, find the longest absolute path to a file
110 | Args:
111 | node(Node): a tree node
112 | Returns:
113 | int: the length of the longest path
114 | '''
115 | if node.is_file: # hit a leaf, and leaf is a file
116 | return len(node.val)
117 | if len(node.subdir) == 0: # hit a leaf but a dir
118 | return 0
119 |
120 | max_len = 0
121 | for sub_node in node.subdir:
122 | max_len = max(max_len, lgst_file_path(sub_node))
123 |
124 | # node.level < 0 means this node is root
125 | length = max_len if node.level < 0 else max_len + len(node.val) + 1
126 |
127 | return length
128 |
129 |
130 | def main():
131 | path_str = 'dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext'
132 | path_str_2 = ('dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext' +
133 | '\ndir2\n\tsubdir1\n\tsubdir2\n\t\tsubsubdir1\n\t\t\tsubsubsubdir3\n\t\t\t\tfile3.ext')
134 | tree = build_tree(path_str_2)
135 | print lgst_file_path(tree.root)
136 |
137 | if __name__ == '__main__':
138 | main()
139 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_18.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Given an array of integers and a number k, where 1 <= k <= length of the array,
5 | compute the maximum values of each subarray of length k.
6 |
7 | For example, given array = [10, 5, 2, 7, 8, 7] and k = 3, we should get:
8 | [10, 7, 8, 8], since:
9 |
10 | 10 = max(10, 5, 2)
11 | 7 = max(5, 2, 7)
12 | 8 = max(2, 7, 8)
13 | 8 = max(7, 8, 7)
14 |
15 | Do this in O(n) time and O(k) space. You can modify the input array in-place and
16 | you do not need to store the results. You can simply print them out as you
17 | compute them.
18 |
19 | Reference:
20 | https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/
21 | '''
22 | from __future__ import print_function
23 | from collections import deque
24 |
25 | # A Deque (Double ended queue) based
26 | # method for printing maximum element
27 | # of all subarrays of size k
28 | def printMax(arr, n, k):
29 | '''Create a Double Ended Queue, q that will store indexes of array elements.
30 | The queue will store indexes of useful elements in every window and it will
31 | maintain decreasing order of values from front to rear in q, i.e.,
32 | arr[q.front[]] to arr[q.rear()] are sorted in decreasing order.
33 |
34 | Args:
35 | arr(list): input array of integers
36 | n(int): length of input array
37 | k(int): window size
38 |
39 | Returns:
40 | None
41 | '''
42 | q = deque()
43 |
44 | # Process first k (or first window) elements of array
45 | for i in range(k):
46 |
47 | # For every element, the previous smaller elements are useless so remove
48 | # them from q
49 | while q and arr[i] >= arr[q[-1]] :
50 | q.pop()
51 |
52 | # Add new element at rear of queue
53 | q.append(i)
54 |
55 | # Process rest of the elements, i.e. from arr[k] to arr[n-1]
56 | for i in range(k, n):
57 |
58 | # The element at the front of the queue is the largest element of
59 | # previous window, so print it
60 | print(str(arr[q[0]]) + " ", end = "")
61 |
62 | # Remove the elements which are out of this window
63 | while q and q[0] <= i-k:
64 | # remove from front of deque
65 | q.popleft()
66 |
67 | # Remove all elements smaller than the currently being added element
68 | # (Remove useless elements)
69 | while q and arr[i] >= arr[q[-1]] :
70 | q.pop()
71 |
72 | # Add current element at the rear of q
73 | q.append(i)
74 |
75 | # Print the maximum element of last window
76 | print(str(arr[q[0]]))
77 |
78 |
79 | def main():
80 | test_arr = [10, 5, 2, 7, 8, 7]
81 | k = 3
82 | printMax(test_arr, len(test_arr), k)
83 |
84 |
85 | if __name__ == '__main__':
86 | main()
87 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_19.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Facebook.
3 |
4 | A builder is looking to build a row of N houses that can be of K different
5 | colors. He has a goal of minimizing cost while ensuring that no two neighboring
6 | houses are of the same color.
7 |
8 | Given an N by K matrix where the nth row and kth column represents the cost to
9 | build the nth house with kth color, return the minimum cost which achieves this
10 | goal.
11 | '''
12 | def solution(costs):
13 | '''
14 | DP by adding a house at a time
15 | Args:
16 | costs(list of list)
17 | Returns:
18 | int
19 | '''
20 | best_cost = [0] * len(costs[0])
21 | for cost in costs: # add a house at a time
22 | temp_cost = [0] * len(costs[0])
23 | for index in xrange(len(cost)):
24 | # best cost is the one for that color plus min cost between every other color
25 | temp_cost[index] = cost[index] + min(best_cost[:index] +
26 | best_cost[index + 1:])
27 | best_cost = temp_cost
28 | print best_cost
29 |
30 | return min(best_cost)
31 |
32 |
33 | def main():
34 | costs = [[2, 1, 1],
35 | [1, 10, 3],
36 | [1, 2, 100]]
37 | print solution(costs)
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_1_two_sum.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was recently asked by Google.
3 |
4 | Given a list of numbers and a number k, return whether any two numbers from the
5 | list add up to k.
6 |
7 | For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17.
8 |
9 | Bonus: Can you do this in one pass?
10 | '''
11 |
12 | # from sets import Set # deprecated, now use 'set' directly
13 |
14 | def solution(list_nums, target):
15 | '''
16 | Use a hash set to store the number we have seen. Then whenever we see a new
17 | number, check whether the difference of it and the target already in the
18 | hash set.
19 |
20 | Args:
21 | list_nums(list): a list of number
22 | target(int): the sum that is looked for
23 |
24 | returns:
25 | bool: whether there is a pair of numbers add up to target
26 | '''
27 | num_seen_set = set()
28 | for num in list_nums:
29 | if target - num in num_seen_set:
30 | return True
31 | else:
32 | num_seen_set.add(num)
33 | return False
34 |
35 |
36 | def main():
37 | test_list = [10, 15, 3, 7]
38 | k = 17
39 | print solution(test_list, k)
40 |
41 |
42 | if __name__ == '__main__':
43 | main()
44 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_2.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Uber.
3 |
4 | Given an array of integers, return a new array such that each element at index i
5 | of the new array is the product of all the numbers in the original array except
6 | the one at i.
7 |
8 | For example, if our input was [1, 2, 3, 4, 5], the expected output would be
9 | [120, 60, 40, 30, 24]. If our input was [3, 2, 1], the expected output would be
10 | [2, 3, 6].
11 |
12 | Follow-up: what if you can't use division?
13 | '''
14 |
15 | def solution(list_nums):
16 | '''
17 | Without using division, have to create a (k,v) dictionary to store the index
18 | and the multiplication result to the left of each num we see in first scan.
19 | Then create the new list by go from right to left in second run. At the same
20 | time, the multiplication to the right need to be stored.
21 |
22 | Args:
23 | list_nums(list): a list of numbers
24 |
25 | Returns:
26 | list: a new list
27 | '''
28 | mul_left = dict()
29 | mul_right = dict()
30 |
31 | new_list = [None] * len(list_nums) # best practice: use None to initiate
32 |
33 | mul_left[-1] = 1
34 | for i in range(len(list_nums) - 1):
35 | mul_left[i] = list_nums[i] * mul_left[i - 1]
36 |
37 | mul_right[len(list_nums)] = 1
38 | for j in reversed(range(len(list_nums))[1:]):
39 | mul_right[j] = list_nums[j] * mul_right[j + 1]
40 |
41 | for i in range(len(list_nums)):
42 | new_list[i] = mul_left[i - 1] * mul_right[i + 1]
43 |
44 | return new_list
45 |
46 | def main():
47 | list_nums = [1, 2, 3, 4, 5]
48 | # list_nums = [3, 2, 1]
49 | # list_nums = []
50 | print solution(list_nums)
51 |
52 | if __name__ == '__main__':
53 | main()
54 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_20.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Given two singly linked lists that intersect at some point, find the intersecting
5 | node. The lists are non-cyclical.
6 |
7 | For example, given A = 1 - > 3 -> 7 -> 8 -> 10 and B = 99 -> 1 -> 8 -> 10,
8 | return the node with value 8.
9 |
10 | In this example, assume nodes with the same value are the exact same node objects.
11 |
12 | Do this in O(M + N) time (where M and N are the lengths of the lists) and
13 | constant space.
14 | '''
15 | class Node(object):
16 | def __init__(self, val=None, next=None):
17 | self.val = val
18 | self.next = next
19 |
20 | def add_node(self, node=None):
21 | self.next = node
22 | return node
23 |
24 |
25 | def find_intersection(A, B):
26 | '''
27 | Find intersection of two singly list
28 | Args:
29 | A(Node)
30 | B(Node)
31 | Returns:
32 | Node: intersection node
33 | '''
34 | while A.val != B.val:
35 | # if A runs to the end first, connect to B, and vice versa
36 | A = B if A.next == None else A.next
37 | B = A if B.next == None else B.next
38 | return A
39 |
40 |
41 | def main():
42 | A = Node(1)
43 | B = Node(99)
44 | A.add_node(Node(3)).add_node(Node(7)).add_node(Node(8)).add_node(Node(10))
45 | B.add_node(Node(99)).add_node(Node(1)).add_node(Node(8)).add_node(Node(10))
46 | print find_intersection(A, B).val
47 |
48 |
49 | if __name__ == '__main__':
50 | main()
51 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_21.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Snapchat.
3 |
4 | Given an array of time intervals (start, end) for classroom lectures (possibly
5 | overlapping), find the minimum number of rooms required.
6 |
7 | For example, given [(30, 75), (0, 50), (60, 150)], you should return 2.
8 | '''
9 | '''
10 | Note:
11 | Minimum Number of Platforms Required for a Railway/Bus Station
12 | https://www.geeksforgeeks.org/minimum-number-platforms-required-railwaybus-station/
13 |
14 | time type room_number
15 | 0 start 1
16 | 30 start 2
17 | 50 end 1
18 | 60 start 2
19 | 75 end 1
20 | 150 end 0
21 | '''
22 | def find_min_rooms(time_list):
23 | '''
24 | Args:
25 | time_list(list)
26 | Returns:
27 | int
28 | '''
29 | start = sorted([num[0] for num in time_list])
30 | end = sorted([num[1] for num in time_list])
31 |
32 | room_occupied = max_room_num = 0
33 | i = j = 0
34 | n = len(time_list)
35 |
36 | while i < n and j < n:
37 | if start[i] < end[j]:
38 | room_occupied += 1
39 | max_room_num = max(room_occupied, max_room_num)
40 | i += 1
41 | else:
42 | room_occupied -= 1
43 | j += 1
44 |
45 | return max_room_num
46 |
47 |
48 | def main():
49 | time_list = [(30, 75), (0, 50), (60, 150)]
50 | time_list2 = [(90,91), (94, 120), (95, 112), (110, 113), (150, 190), (180, 200)]
51 | print find_min_rooms(time_list2)
52 |
53 | if __name__ == '__main__':
54 | main()
55 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_22.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Microsoft.
3 |
4 | Given a dictionary of words and a string made up of those words (no spaces),
5 | return the original sentence in a list. If there is more than one possible
6 | reconstruction, return any of them. If there is no possible reconstruction,
7 | then return null.
8 |
9 | For example, given the set of words 'quick', 'brown', 'the', 'fox', and the
10 | string "thequickbrownfox", you should return ['the', 'quick', 'brown', 'fox'].
11 |
12 | Given the set of words 'bed', 'bath', 'bedbath', 'and', 'beyond', and the
13 | string "bedbathandbeyond", return either ['bed', 'bath', 'and', 'beyond] or
14 | ['bedbath', 'and', 'beyond'].
15 | '''
16 | '''
17 | Note: Wordbreak from Leetcode
18 | https://www.programcreek.com/2012/12/leetcode-solution-word-break/
19 | https://www.programcreek.com/2014/03/leetcode-word-break-ii-java/
20 |
21 | Deep copy a list in python:
22 | https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list
23 | '''
24 |
25 | class Node(object):
26 | def __init__(self, val=None, next_n=None):
27 | self.val = val
28 | self.next = next_n
29 |
30 | def reconstruct(string, dict_set):
31 | '''
32 | Args:
33 | string(String)
34 | dict_set(Set)
35 | Returns:
36 | List
37 | '''
38 | ptr = [None] * (len(string) + 1)
39 |
40 | for i in xrange(len(string)): # traverse each sub string
41 | for j in xrange(i, len(string) + 1):
42 | sub_string = string[i:j]
43 | if sub_string in dict_set:
44 | new_node = Node(sub_string)
45 | if not ptr[j]:
46 | ptr[j] = new_node
47 | else:
48 | add_at_tail(ptr[j], new_node)
49 |
50 | # testing:
51 | # ------------
52 | # for item in ptr:
53 | # print ptr.index(item)
54 | # while item:
55 | # print item.val
56 | # item = item.next
57 |
58 | res = list() # final result
59 | curr = list() # current words found
60 | dfs(ptr, res, curr, len(ptr) - 1) # find out all combinations
61 | return res
62 |
63 |
64 | def add_at_tail(head, node):
65 | '''
66 | Add at the end of the linked list
67 | Args:
68 | head(Node)
69 | node(Node)
70 | Returns:
71 | None
72 | '''
73 | while head.next:
74 | head = head.next
75 | head.next = node
76 |
77 |
78 | def dfs(ptr, result, current, idx):
79 | '''
80 | Args:
81 | ptr(List)
82 | result(List)
83 | current(List)
84 | idx(int)
85 | Returns:
86 | None
87 | '''
88 | if idx == 0: # get to the beginning, dfs ends, add current to result
89 | result.append(current) # reversed: current[::-1] or list(reversed(current))
90 | return
91 |
92 | if not ptr[idx]: # hit a None
93 | return
94 | else: # hit a word
95 | node = ptr[idx]
96 | while node:
97 | word = node.val
98 | # deepcopy: https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list
99 | temp = current[:]
100 | temp.insert(0, word) # normally append(word)
101 | dfs(ptr, result, temp, idx - len(word))
102 | node = node.next
103 |
104 |
105 | def main():
106 | # dict_set = {'quick', 'brown', 'the', 'fox'}
107 | # string = 'thequickbrownfox'
108 | dict_set_2 ={'bed', 'bath', 'bedbath', 'and', 'beyond','dba'}
109 | string_2 = 'bedbathandbeyond'
110 | print reconstruct(string_2, dict_set_2)
111 |
112 |
113 | if __name__ == '__main__':
114 | main()
115 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_23.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | You are given an M by N matrix consisting of booleans that represents a board.
5 | Each True boolean represents a wall. Each False boolean represents a tile you
6 | can walk on.
7 |
8 | Given this matrix, a start coordinate, and an end coordinate, return the minimum
9 | number of steps required to reach the end coordinate from the start. If there is
10 | no possible path, then return null. You can move up, left, down, and right. You
11 | cannot move through walls. You cannot wrap around the edges of the board.
12 |
13 | For example, given the following board:
14 |
15 | [[f, f, f, f],
16 | [t, t, f, t],
17 | [f, f, f, f],
18 | [f, f, f, f]]
19 |
20 | and start = (3, 0) (bottom left) and end = (0, 0) (top left), the minimum number
21 | of steps required to reach the end is 7, since we would need to go through (1, 2)
22 | because there is a wall everywhere else on the second row.
23 | '''
24 | '''
25 | A* Algorithm:
26 | https://www.redblobgames.com/pathfinding/a-star/implementation.html
27 |
28 | def heuristic(a, b):
29 | (x1, y1) = a
30 | (x2, y2) = b
31 | return abs(x1 - x2) + abs(y1 - y2)
32 |
33 | def a_star_search(graph, start, goal):
34 | frontier = PriorityQueue()
35 | frontier.put(start, 0)
36 | came_from = {}
37 | cost_so_far = {}
38 | came_from[start] = None
39 | cost_so_far[start] = 0
40 |
41 | while not frontier.empty():
42 | current = frontier.get()
43 |
44 | if current == goal:
45 | break
46 |
47 | for next in graph.neighbors(current):
48 | new_cost = cost_so_far[current] + graph.cost(current, next)
49 | if next not in cost_so_far or new_cost < cost_so_far[next]:
50 | cost_so_far[next] = new_cost
51 | priority = new_cost + heuristic(goal, next)
52 | frontier.put(next, priority)
53 | came_from[next] = current
54 |
55 | return came_from, cost_so_far
56 | '''
57 | '''
58 | Refer to:
59 | https://github.com/r1cc4rdo/daily_coding_problem/blob/master/daily_coding_problem_21_25.py
60 | '''
61 | def find_shortest_path(map, start, end):
62 | coords = [(index_r, index_c) for index_r, row in enumerate(map)
63 | for index_c, element in enumerate(row) if not element]
64 |
65 | current_distance = 0
66 | distances = [[None for col in xrange(len(map[0]))] for row in xrange(len(map))]
67 | distances[start[0]][start[1]] = 0
68 | while True:
69 |
70 | wavefront = [coord for coord in coords if distances[coord[0]][coord[1]] == current_distance]
71 | if not wavefront:
72 | break
73 |
74 | current_distance += 1
75 | for node in wavefront:
76 |
77 | neighbours = [coord for coord in coords if (abs(node[0] - coord[0]) + abs(node[1] - coord[1])) == 1]
78 | for n in neighbours:
79 | if distances[n[0]][n[1]] is None:
80 | distances[n[0]][n[1]] = current_distance
81 |
82 | return distances[end[0]][end[1]]
83 |
84 |
85 | def main():
86 | map = [[False, False, False, False],
87 | [True, True, False, True],
88 | [False, False, False, False],
89 | [False, False, False, False]]
90 | print find_shortest_path(map, (3, 0), (0, 0))
91 |
92 |
93 | if __name__ == '__main__':
94 | main()
95 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_24.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Implement locking in a binary tree. A binary tree node can be locked or unlocked
5 | only if all of its descendants or ancestors are not locked.
6 |
7 | Design a binary tree node class with the following methods:
8 |
9 | is_locked, which returns whether the node is locked
10 |
11 | lock, which attempts to lock the node. If it cannot be locked, then it should
12 | return false. Otherwise, it should lock it and return true.
13 |
14 | unlock, which unlocks the node. If it cannot be unlocked, then it should return
15 | false. Otherwise, it should unlock it and return true.
16 |
17 | You may augment the node to add parent pointers or any other property you would
18 | like. You may assume the class is used in a single-threaded program, so there is
19 | no need for actual locks or mutexes. Each method should run in O(h), where h is
20 | the height of the tree.
21 | '''
22 | '''
23 | Reference:
24 | https://www.dailycodingproblem.com/blog/lockable-binary-trees/
25 | '''
26 |
27 | class LockingBinaryTreeNode(object):
28 | def __init__(self, val, left=None, right=None, parent=None):
29 | self.val = val
30 | self.left = left
31 | self.right = right
32 | self.parent = parent
33 | self._is_locked = False
34 | self.locked_descendants_count = 0
35 |
36 |
37 | def _can_lock_or_unlock(self):
38 | if self.locked_descendants_count > 0:
39 | return False
40 |
41 | cur = self.parent
42 | while cur:
43 | if cur._is_locked:
44 | return False
45 | cur = cur.parent
46 | return True
47 |
48 |
49 | def is_locked(self):
50 | return self._is_locked
51 |
52 |
53 | def lock(self):
54 | if self._can_lock_or_unlock():
55 | # Not locked, so update is_locked and increment count in all ancestors
56 | self._is_locked = True
57 |
58 | cur = self.parent
59 | while cur:
60 | cur.locked_descendants_count += 1
61 | cur = cur.parent
62 | return True
63 | else:
64 | return False
65 |
66 |
67 | def unlock(self):
68 | if self._can_lock_or_unlock():
69 | self._is_locked = False
70 |
71 | # Update count in all ancestors
72 | cur = self.parent
73 | while cur:
74 | cur.locked_descendants_count -= 1
75 | cur = cur.parent
76 | return True
77 | else:
78 | return False
79 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_25_regular_expression_matching.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Facebook.
3 |
4 | Implement regular expression matching with the following special characters:
5 |
6 | . (period) which matches any single character
7 | * (asterisk) which matches zero or more of the preceding element
8 |
9 | That is, implement a function that takes in a string and a valid regular
10 | expression and returns whether or not the string matches the regular expression.
11 |
12 | For example, given the regular expression "ra." and the string "ray", your
13 | function should return true. The same regular expression on the string "raymond"
14 | should return false.
15 |
16 | Given the regular expression ".*at" and the string "chat", your function should
17 | return true. The same regular expression on the string "chats" should return false.
18 | '''
19 | '''
20 | Resource:
21 | Youtube: https://www.youtube.com/watch?v=l3hda49XcDE
22 | '''
23 |
24 | def isMatch(self, s, p):
25 | m, n = len(s), len(p)
26 | DP = [[False]*(n+1) for i in range(m+1)]
27 | DP[0][0] = True
28 | for i in range(m+1):
29 | for j in range(1,n+1):
30 | if p[j-1] == '*':
31 | DP[i][j] = DP[i][j-2] or (i > 0 and j > 1 and (p[j-2] == '.' or
32 | s[i-1] == p[j-2]) and DP[i-1][j])
33 | elif i > 0 and (p[j-1] == '.' or p[j-1] == s[i-1]):
34 | DP[i][j] = DP[i-1][j-1]
35 | return DP[m][n]
36 |
37 |
38 | def main():
39 | s = 'ray'
40 | p = '.a.'
41 | print isMatch(s, p)
42 |
43 |
44 | if __name__ == '__main__':
45 | main()
46 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_26.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Given a singly linked list and an integer k, remove the kth last element from
5 | the list. k is guaranteed to be smaller than the length of the list.
6 |
7 | The list is very long, so making more than one pass is prohibitively expensive.
8 |
9 | Do this in constant space and in one pass.
10 | '''
11 | class Node(object):
12 | def __init__(self, val=None, next_n=None):
13 | self.val = val
14 | self.next = next_n
15 |
16 | def __str__(self):
17 | values = []
18 | while self:
19 | values.append(str(self.val))
20 | self = self.next
21 | return ' -> '.join(values)
22 |
23 | def add_node(self, node):
24 | self.next = node
25 | return node
26 |
27 |
28 | def remove_k_last_elem(head, k):
29 | '''
30 | Use two pointers trick to access the kth last elem in one pass
31 | Args:
32 | head(Node): head of the linked list
33 | k(int)
34 | Returns:
35 | Node: head of the new linked list
36 | '''
37 | slow = fast = head
38 | for _ in xrange(k):
39 | fast = fast.next
40 |
41 | while fast.next:
42 | slow = slow.next
43 | fast = fast.next
44 |
45 | slow.next = slow.next.next
46 | return head
47 |
48 |
49 | def main():
50 | curr = head = Node(0)
51 | for i in xrange(1, 10):
52 | new_node = Node(i)
53 | curr = curr.add_node(new_node)
54 |
55 | print head
56 | remove_k_last_elem(head, 4)
57 | print head
58 |
59 |
60 | if __name__ == '__main__':
61 | main()
62 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_27.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Facebook.
3 |
4 | Given a string of round, curly, and square open and closing brackets, return
5 | whether the brackets are balanced (well-formed).
6 |
7 | For example, given the string "([])[]({})", you should return true.
8 |
9 | Given the string "([)]" or "((()", you should return false.
10 | '''
11 |
12 | def is_balanced_method_2(brackets):
13 | '''
14 | Reference:
15 | https://github.com/r1cc4rdo/daily_coding_problem/blob/master/daily_coding_problem_26_30.py#L35
16 |
17 | Note:
18 | reduce() accept 3 arguments:
19 | https://stackoverflow.com/questions/19589233/reduce-function-with-three-parameters
20 | The third argument is used as initializer
21 |
22 | The functools.reduce() documentation includes a Python version of the function:
23 | def reduce(function, iterable, initializer=None):
24 | it = iter(iterable)
25 | if initializer is None:
26 | value = next(it)
27 | else:
28 | value = initializer
29 | for element in it:
30 | value = function(value, element)
31 | return value
32 | '''
33 | copy = None
34 | while brackets and brackets != copy:
35 |
36 | copy = brackets
37 | brackets = reduce(lambda s, p: s.replace(p, ''), ['()', '[]', '{}'], brackets)
38 |
39 | return brackets == ''
40 |
41 |
42 | def is_balanced(brackets):
43 | open_brackets = ['(', '[', '{']
44 | close_brackets = [')', ']', '}']
45 | dictionary = {')': '(', ']': '[', '}': '{'}
46 |
47 | br_stack = []
48 |
49 | for br in brackets:
50 | if br in open_brackets:
51 | br_stack.append(br)
52 | elif br in close_brackets:
53 | if match(br_stack, br, dictionary): # balance
54 | br_stack.pop()
55 | else:
56 | return False
57 | else:
58 | raise ValueError('Invalid String.')
59 |
60 | if not br_stack:
61 | return True
62 | else:
63 | return False
64 |
65 |
66 | def match(br_list, br, dic):
67 | if not br_list:
68 | return False
69 | else:
70 | if br_list[-1] == dic[br]:
71 | return True
72 | else:
73 | return False
74 |
75 |
76 | def main():
77 | '''
78 | >>> is_balanced('(({[]})}')
79 | False
80 |
81 | >>> is_balanced('..{}')
82 | Traceback (most recent call last):
83 | ...
84 | ValueError: Invalid String.
85 |
86 | >>> is_balanced('([])[]({})')
87 | True
88 |
89 | >>> is_balanced('([)]')
90 | False
91 |
92 | >>> is_balanced_method_2('([])[]({})')
93 | True
94 | '''
95 | import doctest
96 | doctest.testmod(verbose=True)
97 |
98 |
99 | if __name__ == '__main__':
100 | main()
101 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_28.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Palantir.
3 |
4 | Write an algorithm to justify text. Given a sequence of words and an integer
5 | line length k, return a list of strings which represents each line, fully
6 | justified.
7 |
8 | More specifically, you should have as many words as possible in each line.
9 | There should be at least one space between each word. Pad extra spaces when
10 | necessary so that each line has exactly length k. Spaces should be distributed
11 | as equally as possible, with the extra spaces, if any, distributed starting
12 | from the left.
13 |
14 | If you can only fit one word on a line, then you should pad the right-hand side
15 | with spaces.
16 |
17 | Each word is guaranteed not to be longer than k.
18 |
19 | For example, given the list of words
20 | ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"] and
21 | k = 16, you should return the following:
22 |
23 | ["the quick brown", # 1 extra space on the left
24 | "fox jumps over", # 2 extra spaces distributed evenly
25 | "the lazy dog"] # 4 extra spaces distributed evenly
26 | '''
27 |
28 | def justify_words(words, k):
29 | '''
30 | Justify a list of words
31 | Args:
32 | words(list)
33 | k(int)
34 | Returns:
35 | list
36 | '''
37 | res = []
38 |
39 | len_words = num_word = 0
40 | line_words = []
41 |
42 | for word in words:
43 | if len(word) + len_words + num_word > k:
44 | line = justify_line(line_words, k, len_words, num_word)
45 | res.append(line)
46 |
47 | # re-initialize
48 | len_words = num_word = 0
49 | line_words = []
50 |
51 | line_words.append(word)
52 | len_words += len(word)
53 | num_word += 1
54 |
55 | if line_words:
56 | line = justify_line(line_words, k, len_words, num_word)
57 | res.append(line)
58 | return res
59 |
60 |
61 | def justify_line(line_words, k, len_words, num_word):
62 | '''
63 | Args:
64 | line_words(list)
65 | k(int)
66 | len_words(int)
67 | num_word(int)
68 | Returns:
69 | string
70 | '''
71 | if num_word == 1:
72 | return line_words[0] + ' ' * (k - len(line_words[0]))
73 |
74 | num_space_total = k - len_words
75 | remainder = num_space_total % (num_word - 1)
76 | num_space = num_space_total / (num_word - 1)
77 |
78 | if remainder == 0: # spaces are equally distributed
79 | space = ' ' * num_space
80 | return space.join(line_words)
81 | else: # front half has more space than latter half
82 | space = ' ' * num_space
83 | line_words[remainder] = space.join(line_words[remainder:])
84 | front_space = ' ' * (num_space + 1)
85 | return front_space.join(line_words[:remainder + 1])
86 |
87 |
88 | def main():
89 | '''
90 | >>> words = ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
91 | >>> k = 16
92 | >>> justify_words(words, k)
93 | ['the quick brown', 'fox jumps over', 'the lazy dog']
94 |
95 | >>> words = ['the']
96 | >>> k = 5
97 | >>> justify_words(words, k)
98 | ['the ']
99 |
100 | >>> words = ["the", "quick", "brown", "fox"]
101 | >>> k = 16
102 | >>> justify_words(words, k)
103 | ['the quick brown', 'fox ']
104 | '''
105 |
106 | import doctest
107 | doctest.testmod(verbose = True)
108 |
109 |
110 | if __name__ == '__main__':
111 | main()
112 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_29.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Amazon.
3 |
4 | Run-length encoding is a fast and simple method of encoding strings. The basic
5 | idea is to represent repeated successive characters as a single count and
6 | character. For example, the string "AAAABBBCCDAA" would be encoded as
7 | "4A3B2C1D2A".
8 |
9 | Implement run-length encoding and decoding. You can assume the string to be
10 | encoded have no digits and consists solely of alphabetic characters. You can
11 | assume the string to be decoded is valid.
12 | '''
13 |
14 | def encoding(string):
15 | '''
16 | >>> encoding('AAAABBBCCDAA')
17 | '4A3B2C1D2A'
18 | >>> encoding('')
19 | ''
20 | >>> encoding('AaaB')
21 | '1A2a1B'
22 | '''
23 | if not string:
24 | return ''
25 |
26 | coding = []
27 |
28 | code = string[0]
29 | for char in string[1:]:
30 | if char != code[-1]:
31 | coding.append(str(len(code)) + code[-1])
32 | code = char
33 | else:
34 | code += char
35 |
36 | if code:
37 | coding.append(str(len(code)) + code[-1])
38 |
39 | return ''.join(coding)
40 |
41 | def decoding(code):
42 | '''
43 | >>> decoding('4A3B2C1D2A')
44 | 'AAAABBBCCDAA'
45 | >>> decoding('')
46 | ''
47 | >>> decoding('1A2a1B')
48 | 'AaaB'
49 | '''
50 | if not code:
51 | return ''
52 |
53 | decoding = []
54 | while code:
55 | to_decode = code[:2]
56 | string = to_decode[1] * int(to_decode[0])
57 | decoding.append(string)
58 | code = code[2:] if len(code) > 2 else []
59 | return ''.join(decoding)
60 |
61 |
62 | def others(rle):
63 | '''
64 | Refer:
65 | https://github.com/r1cc4rdo/daily_coding_problem/blob/master/daily_coding_problem_26_30.py#L97
66 | >>> others('AAAABBBCCDAA')
67 | '4A3B2C1D2A'
68 | >>> others('4A3B2C1D2A')
69 | 'AAAABBBCCDAA'
70 | '''
71 | if rle.isalpha(): # no numbers, encode
72 |
73 | encoded = ''
74 | while rle:
75 |
76 | idx = 0
77 | while idx < len(rle) and rle[0] == rle[idx]:
78 | idx += 1
79 |
80 | encoded += str(idx) + rle[0]
81 | rle = rle[idx:]
82 |
83 | return encoded
84 |
85 | else: # decode
86 |
87 | return ''.join(c * int(n) for n, c in zip(rle[::2], rle[1::2]))
88 |
89 |
90 | if __name__ == '__main__':
91 | import doctest
92 | doctest.testmod(verbose = True)
93 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_30.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Facebook.
3 |
4 | You are given an array of non-negative integers that represents a two-dimensional
5 | elevation map where each element is unit-width wall and the integer is the height.
6 | Suppose it will rain and all spots between two walls get filled up.
7 |
8 | Compute how many units of water remain trapped on the map in O(N) time and O(1)
9 | space.
10 |
11 | For example, given the input [2, 1, 2], we can hold 1 unit of water in the middle.
12 |
13 | Given the input [3, 0, 1, 3, 0, 5], we can hold 3 units in the first index, 2 in
14 | the second, and 3 in the fourth index (we cannot hold 5 since it would run off
15 | to the left), so we can trap 8 units of water.
16 | '''
17 | '''
18 | Note:
19 | https://www.geeksforgeeks.org/trapping-rain-water/
20 |
21 | https://github.com/r1cc4rdo/daily_coding_problem/blob/master/daily_coding_problem_26_30.py#L129
22 | '''
23 | def water_cnt(arr):
24 | water = 0
25 |
26 | while len(arr) > 2:
27 | # the idea is: from the smallest left/right boundary, accumulate water
28 | # level until reaching a higher wall inside. Then recurse with with the
29 | # new bound, until only two array entries.
30 | lval = arr[0]
31 | rval = arr[-1]
32 | if lval <= rval:
33 |
34 | cnt = 1
35 | while arr[cnt] < arr[0]:
36 | water += arr[0] - arr[cnt]
37 | cnt += 1
38 |
39 | arr = arr[cnt:]
40 |
41 | else:
42 |
43 | cnt = -2
44 | while arr[cnt] < arr[-1]:
45 | water += arr[-1] - arr[cnt]
46 | cnt -= 1
47 |
48 | arr = arr[:cnt + 1]
49 | # print water, arr
50 | return water
51 |
52 |
53 | def main():
54 | '''
55 | >>> arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
56 | >>> water_cnt(arr)
57 | 6
58 |
59 | >>> arr = [3, 0, 1, 3, 0, 5]
60 | >>> water_cnt(arr)
61 | 8
62 |
63 | >>> arr = [2, 1, 2]
64 | >>> water_cnt(arr)
65 | 1
66 | '''
67 | pass
68 |
69 | if __name__ == '__main__':
70 | import doctest
71 | doctest.testmod(verbose=True)
72 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_3_serializer.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Given the root to a binary tree, implement serialize(root), which serializes the
5 | tree into a string, and deserialize(s), which deserializes the string back into
6 | the tree.
7 |
8 | For example, given the following Node class
9 |
10 | class Node:
11 | def __init__(self, val, left=None, right=None):
12 | self.val = val
13 | self.left = left
14 | self.right = right
15 | The following test should pass:
16 |
17 | node = Node('root', Node('left', Node('left.left')), Node('right'))
18 | assert deserialize(serialize(node)).left.left.val == 'left.left'
19 | '''
20 |
21 | class Node(object):
22 | '''
23 | Args:
24 | val(any)
25 | left(Node)
26 | right(Node)
27 | '''
28 | def __init__(self, val, left=None, right=None):
29 | self.val = val
30 | self.left = left
31 | self.right = right
32 |
33 |
34 | def serialize(tree_node):
35 | '''
36 | Use -1 to represent an empty leaf. Use ' ' to sperate different nodes.
37 |
38 | Args:
39 | tree_root(class Node): the root of the tree
40 |
41 | Returns:
42 | string: a serialized tree
43 | '''
44 | preorder_list = preorder_trav(tree_node)
45 | return ' '.join(str(x) for x in preorder_list)
46 |
47 |
48 | def preorder_trav(node):
49 | '''
50 | Args:
51 | node(class Node): a node on which the traverse starts
52 |
53 | Returns:
54 | list: pre-order traverse
55 | '''
56 | tree_list = []
57 | if node is not None:
58 | tree_list.append(node.val)
59 | tree_list.extend(preorder_trav(node.left))
60 | tree_list.extend(preorder_trav(node.right))
61 |
62 | if node is None:
63 | tree_list.append('-1')
64 | return tree_list
65 |
66 |
67 | def deserialize(tree_string):
68 | '''
69 | Args:
70 | tree_string(string): a serialized tree representation
71 |
72 | Returns:
73 | class Node: the root of a tree
74 | '''
75 | tree_list = tree_string.split(' ')
76 | tree = rebuild(tree_list)
77 | return tree
78 |
79 |
80 | def rebuild(tree_list):
81 | '''
82 | Args:
83 | tree_list: a list of all nodes in a tree
84 |
85 | Returns:
86 | class Node: the root of a tree
87 | '''
88 | if len(tree_list) != 0: # use == to compare value, 'is' to compare objects
89 | value = tree_list.pop(0)
90 | if value != '-1': # use == or != to compare two strings
91 | node = Node(value)
92 | node.left = rebuild(tree_list)
93 | node.right = rebuild(tree_list)
94 | else:
95 | node = Node(None)
96 | return node
97 |
98 |
99 | def main():
100 | '''
101 | unit test
102 | '''
103 | node = Node('root', Node('left', Node('left.left')), Node('right'))
104 | # node = Node('root')
105 | print serialize(node)
106 | print deserialize(serialize(node)).val
107 | print deserialize(serialize(node)).left.val
108 | print deserialize(serialize(node)).left.left.val
109 | print deserialize(serialize(node)).right.val
110 |
111 |
112 | if __name__ == '__main__':
113 | main()
114 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_4.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Stripe.
3 |
4 | Given an array of integers, find the first missing positive integer in linear
5 | time and constant space. In other words, find the lowest positive integer that
6 | does not exist in the array. The array can contain duplicates and negative
7 | numbers as well.
8 |
9 | For example, the input [3, 4, -1, 1] should give 2. The input [1, 2, 0] should
10 | give 3.
11 |
12 | You can modify the input array in-place.
13 |
14 | -----------
15 |
16 | Some other thoughts:
17 |
18 | A naive method to solve this problem is to search all positive integers, starting
19 | from 1 in the given array. We may have to search at most n+1 numbers in the given
20 | array. So this solution takes O(n^2) in worst case.
21 |
22 | We can use sorting to solve it in lesser time complexity. We can sort the array
23 | in O(nLogn) time. Once the array is sorted, then all we need to do is a linear
24 | scan of the array. So this approach takes O(nLogn + n) time which is O(nLogn).
25 |
26 | We can also use hashing. We can build a hash table of all positive elements in
27 | the given array. Once the hash table is built. We can look in the hash table for
28 | all positive integers, starting from 1. As soon as we find a number which is not
29 | there in hash table, we return it. This approach may take O(n) time on average,
30 | but it requires O(n) extra space.
31 | '''
32 |
33 | def solution(alist):
34 | '''
35 | Use the index of the list to denote whether we have seen this number.
36 | For example:
37 | We see 2, then change the number on index 2 from + to -.
38 | [2, 4, 1] --> [2, 4, -1]
39 |
40 | ------
41 | Args:
42 | alist(list): a list of numbers may includes duplicates and negative
43 | Returns:
44 | int: the smallest positive integer missing in the given list
45 | '''
46 | pos_list = remove_negative(alist)
47 | modify_index(pos_list)
48 | smallest_pos = find_smallest_pos(pos_list)
49 | return smallest_pos
50 |
51 |
52 | def remove_negative(alist):
53 | '''
54 | Args:
55 | alist(list): a list of numbers may includes duplicates and negative
56 | Returns:
57 | list: a list of numbers may includes only duplicates, no negative and 0
58 | '''
59 |
60 | '''
61 | Note:
62 | When reading, 'alist' is a reference to the original 'list', and 'list[:]'
63 | shallow-copies the list.
64 |
65 | When assigning, 'alist' (re)binds the name and 'alist[:]' slice-assigns,
66 | replacing what was previously in the list.
67 | '''
68 | # filter seems not an in-place modification
69 | # new_list = list(filter(lambda x: x > 0, alist))
70 |
71 | # following is not an in-place way either
72 | # alist = [x for x in alist if x > 0]
73 |
74 | # finally, this seems like an in-place operate as the id(alist) remains same
75 | # correct me if I'm wrong
76 | alist[:] = [x for x in alist if x > 0]
77 | return alist
78 |
79 |
80 | def modify_index(pos_list):
81 | '''
82 | Args:
83 | pos_list(list)
84 | Returns:
85 | list
86 | '''
87 | for num in pos_list:
88 | if abs(num) - 1 < len(pos_list) and pos_list[abs(num) - 1] > 0:
89 | pos_list[abs(num) - 1] = - pos_list[abs(num) - 1]
90 |
91 |
92 | def find_smallest_pos(pos_list):
93 | # return pos_list
94 | '''
95 | Args:
96 | pos_list(list)
97 | Returns:
98 | int
99 | '''
100 | for idx, num in enumerate(pos_list):
101 | if num > 0:
102 | return idx + 1
103 | return len(pos_list) + 1
104 |
105 |
106 | def main():
107 | # test_list = [3, 4, -1, 1]
108 | # test_list = [1, 2, 0]
109 | test_list = [2, 4, -8, 10, 15, 0, 0 , -1, 1]
110 | # test_list = [0, 0, 0]
111 | print solution(test_list)
112 |
113 |
114 | if __name__ == '__main__':
115 | main()
116 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_5.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Jane Street.
3 |
4 | cons(a, b) constructs a pair, and car(pair) and cdr(pair) returns the first and
5 | last element of that pair. For example, car(cons(3, 4)) returns 3, and
6 | cdr(cons(3, 4)) returns 4.
7 |
8 | Given this implementation of cons:
9 |
10 | def cons(a, b):
11 | def pair(f):
12 | return f(a, b)
13 | return pair
14 | Implement car and cdr.
15 | '''
16 |
17 | def cons(a, b):
18 | '''
19 | Args:
20 | a(int)
21 | b(int)
22 | Returns:
23 | function: a function has another function 'f' as argument
24 | '''
25 | def pair(f):
26 | '''
27 | Args:
28 | f(function)
29 | Returns:
30 | function: that has a, b as two arguments
31 | '''
32 | return f(a, b)
33 | return pair
34 |
35 |
36 | def car(func):
37 | '''
38 | Args:
39 | func(function)
40 | Returns:
41 | function: define the function 'f'
42 | '''
43 | # method 1
44 | return func(lambda x, y: x)
45 |
46 | # method 2
47 | # ------------
48 | # def f(a, b):
49 | # return a
50 | # return func(f)
51 |
52 |
53 | def cdr(func):
54 | '''
55 | Args:
56 | func(function)
57 | Returns:
58 | function: define the function 'f'
59 | '''
60 | return func(lambda x, y: y)
61 |
62 |
63 | def main():
64 | print car(cons(3, 4))
65 | print cdr(cons(3, 4))
66 |
67 |
68 | if __name__ == '__main__':
69 | main()
70 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_6.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | An XOR linked list is a more memory efficient doubly linked list. Instead of each
5 | node holding next and prev fields, it holds a field named both, which is a XOR of
6 | the next node and the previous node. Implement a XOR linked list; it has an
7 | add(element) which adds the element to the end, and a get(index) which returns
8 | the node at index.
9 |
10 | If using a language that has no pointers (such as Python), you can assume you
11 | have access to 'get_pointer' and 'dereference_pointer' functions that converts
12 | between nodes and memory addresses.
13 |
14 | ----------
15 | XOR
16 | 0 0 0
17 | 0 1 1
18 | 1 0 1
19 | 1 1 1
20 | ----------
21 |
22 | XOR Linked List:
23 | None -> Node(A) -> Node(B) -> ... -> Node(X) -> None
24 |
25 | num_A = 0 XOR address(B)
26 | num_B = address(A) XOR address(C)
27 | ...
28 | num_X = address(W) XOR address(Y)
29 | '''
30 |
31 | '''
32 | I think this problem will only show up for C and C++.
33 | There is no way to do it in python or JAVA.
34 | '''
35 |
36 | class Node(object):
37 | def __init__(self, val = None, both = None):
38 | self.val = val
39 | self.both = None
40 |
41 | class XOR_List(object):
42 | def __init__(self, Node = None):
43 | self.head = Node(0, 0)
44 | self.tail = Node(0, 0)
45 | self.length = 0
46 |
47 | def add(self, element):
48 | if length == 0:
49 | self.head.both = 0 ^ get_pointer(element)
50 | self.tail.both = get_pointer(element) ^ 0
51 | element.both = get_pointer(self.head) ^ get_pointer(self.tail)
52 | else:
53 | prev = dereference_pointer(self.tail.both)
54 | prev_prev_addr = prev.both ^ get_pointer(self.tail)
55 | prev.both = prev_prev_addr ^ get_pointer(element)
56 | element.both = get_pointer(prev) ^ get_pointer(self.tail.both)
57 | self.tail.both = get_pointer(element) ^ 0
58 | length += 1
59 |
60 | def get(self, index):
61 | if index >= length:
62 | raise ValueError('Invalid Index!')
63 | else:
64 | ptr = self.head.both
65 | prev_addr = get_pointer(self.head)
66 |
67 | while index > 0:
68 | node = dereference_pointer(ptr)
69 | ptr = node.both ^ prev_addr
70 | prev_addr = ptr
71 | index -= 1
72 |
73 | if index == 0:
74 | return dereference_pointer(ptr)
75 |
76 |
77 | def main():
78 | pass
79 |
80 |
81 | if __name__ == '__main__':
82 | main()
83 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_7.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Facebook.
3 |
4 | Given the mapping a = 1, b = 2, ... z = 26, and an encoded message, count the
5 | number of ways it can be decoded.
6 |
7 | For example, the message '111' would give 3, since it could be decoded as 'aaa',
8 | 'ka', and 'ak'.
9 |
10 | You can assume that the messages are decodable. For example, '001' is not allowed.
11 |
12 | '''
13 | '''
14 | Not sure if '10001' is valid;
15 |
16 | Question: How do deal with 0 if there are any?
17 | Let's just assume there is no ZERO in the message;
18 | '''
19 |
20 |
21 | def solution(message):
22 | '''
23 | To decode message.
24 | Args:
25 | message(string)
26 | Returns:
27 | int
28 | '''
29 | # return decode_cnt(list(message))
30 | return decode_cnt_no_zero(list(message))
31 |
32 |
33 | def decode_cnt_no_zero(msg_list):
34 | '''
35 | Args:
36 | msg_list(list)
37 | Returns:
38 | int
39 | '''
40 | if len(msg_list) <= 1:
41 | return 1
42 |
43 | if len(msg_list) >= 2:
44 | if 1 <= int(''.join(msg_list[0:2])) <= 26:
45 | return (decode_cnt_no_zero(msg_list[1:]) +
46 | decode_cnt_no_zero(msg_list[2:]))
47 | return decode_cnt_no_zero(msg_list[1:])
48 |
49 | """
50 | def decode_cnt(msg_list):
51 | '''
52 | A solution trying to solve when there are zeros.
53 | Args:
54 | msg_list(list): the list of message waiting for decoding
55 | Returns:
56 | int: count of how many ways to decode
57 | '''
58 | if len(msg_list) == 1:
59 | return 1 if int(msg_list[0]) != 0 else 0
60 |
61 | if len(msg_list) == 2:
62 | count = 0
63 | if int(msg_list[0]) != 0 and int(msg_list[1]) != 0:
64 | count += 1
65 | if 1 <= int(''.join(msg_list)) <= 26:
66 | count += 1
67 | return count
68 |
69 | if len(msg_list) > 2:
70 | count = 0
71 | if int(msg_list[0]) != 0:
72 | count += decode_cnt(msg_list[1:])
73 | if 1 <= int(''.join(msg_list[0:2])) <= 26:
74 | count += decode_cnt(msg_list[2:])
75 | return count
76 | """
77 |
78 | def main():
79 | msg = '1119'
80 | print solution(msg)
81 |
82 | if __name__ == '__main__':
83 | main()
84 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_8.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | A unival tree (which stands for "universal value") is a tree where all nodes
5 | under it have the same value.
6 |
7 | Given the root to a binary tree, count the number of unival subtrees.
8 |
9 | For example, the following tree has 5 unival subtrees:
10 |
11 | 0
12 | / \
13 | 1 0
14 | / \
15 | 1 0
16 | / \
17 | 1 1
18 | '''
19 | class Node(object):
20 | '''
21 | Tree Node
22 | If the tree rooted at this node is a unival tree, then 'is_unival' == True
23 | '''
24 | def __init__(self, val=None, left=None, right=None, is_unival=False):
25 | self.val = val
26 | self.left = left
27 | self.right = right
28 | self.is_unival = is_unival
29 |
30 |
31 | def count_unival_subtree(node):
32 | '''
33 | Args:
34 | node(Node): The root node of a sub-tree
35 |
36 | Returns:
37 | int
38 | '''
39 | if node.left == node.right == None:
40 | node.is_unival = True
41 | return 1
42 |
43 | left = 0
44 | right = 0
45 | if node.left != None:
46 | left = count_unival_subtree(node.left)
47 | if node.right != None:
48 | right = count_unival_subtree(node.right)
49 |
50 | if node.left and node.right: # node has both left and right
51 | if (node.left.is_unival and node.right.is_unival
52 | and node.val == node.left.val == node.right.val):
53 | node.is_unival = True
54 | return left + right + 1
55 | else:
56 | return left + right
57 | else: # either left or right is missing
58 | if ((not node.left and node.val == node.right.val and node.right.is_unival)
59 | or (not node.right and node.val == node.left.val and node.left.is_unival)):
60 | node.is_unival = True
61 | return left + right + 1
62 | else:
63 | return left + right
64 |
65 |
66 | def main():
67 | root = Node('0', Node('1'), Node('0', Node('1', Node('1'), Node('1')), Node('0')))
68 | print count_unival_subtree(root)
69 |
70 |
71 | if __name__ == '__main__':
72 | main()
73 |
--------------------------------------------------------------------------------
/Problem 1-30/problem_9.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Airbnb.
3 |
4 | Given a list of integers, write a function that returns the largest sum of
5 | non-adjacent numbers. Numbers can be 0 or negative.
6 |
7 | For example, [2, 4, 6, 2, 5] should return 13, since we pick 2, 6, and 5.
8 | [5, 1, 1, 5] should return 10, since we pick 5 and 5.
9 |
10 | Follow-up: Can you do this in O(N) time and constant space?
11 | '''
12 |
13 | def find_max_sum(int_list):
14 | '''
15 | Use Dynamic Programming to find the max sum of non-adjacent numbers.
16 | Args:
17 | int_list(list): a list of integers that may have 0 or negative
18 | Returns:
19 | int
20 | '''
21 | if not int_list:
22 | return 0
23 | elif len(int_list) <= 2:
24 | return max(int_list)
25 |
26 | last_num = int_list[-1] # last number in the list
27 | with_last = find_max_sum(int_list[:-2]) + last_num # sum include last_num
28 | without_last = find_max_sum(int_list[:-1]) # sum without last_num
29 | return max(with_last, without_last)
30 |
31 |
32 | def main():
33 | # test_list = [2, 4, 6, 2, 5]
34 | # test_list = [5, 1, 1, 5]
35 | test_list = [-8, 4, -3, 2, 3, 4]
36 | print find_max_sum(test_list)
37 |
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/Problem 31-60/problem_31.py:
--------------------------------------------------------------------------------
1 | # -- coding: utf-8 --
2 | '''
3 | This problem was asked by Google.
4 |
5 | The edit distance between two strings refers to the minimum number of character
6 | insertions, deletions, and substitutions required to change one string to the
7 | other. For example, the edit distance between “kitten” and “sitting” is three:
8 | substitute the 'k' for 's', substitute the 'e' for 'i', and append a 'g'.
9 |
10 | Given two strings, compute the edit distance between them.
11 | '''
12 | def edit_distance(str1, str2):
13 | '''
14 | Dynamic Programming
15 | Args:
16 | str1(string)
17 | str2(string)
18 | Returns:
19 | int
20 | '''
21 | m, n = len(str1), len(str2)
22 |
23 | dp = [[0] * (n+1) for i in xrange(m+1)]
24 |
25 | for i in xrange(n+1):
26 | dp[0][i] = i
27 |
28 | for j in xrange(m+1):
29 | dp[j][0] = j
30 |
31 | for i in xrange(1, m+1):
32 | for j in xrange(1, n+1):
33 | if str1[i-1] == str2[j-1]:
34 | dp[i][j] = dp[i-1][j-1]
35 | else:
36 | dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
37 |
38 | return dp[m][n]
39 |
40 |
41 | def main():
42 | '''
43 | >>> edit_distance('kitten', 'sitting')
44 | 3
45 | >>> edit_distance('', '')
46 | 0
47 | >>> edit_distance('', 'hi')
48 | 2
49 | '''
50 | import doctest
51 | doctest.testmod(verbose=True)
52 |
53 | if __name__ == '__main__':
54 | main()
55 |
--------------------------------------------------------------------------------
/Problem 31-60/problem_32.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Jane Street.
3 |
4 | Suppose you are given a table of currency exchange rates, represented as a 2D
5 | array. Determine whether there is a possible arbitrage: that is, whether there
6 | is some sequence of trades you can make, starting with some amount A of any
7 | currency, so that you can end up with some amount greater than A of that
8 | currency.
9 |
10 | There are no transaction costs and you can trade fractional quantities.
11 | '''
12 | '''
13 | Note:
14 | https://www.dailycodingproblem.com/blog/how-to-find-arbitrage-opportunities-in-python/
15 |
16 | We can model the currencies and the exchange rates as a graph, where the nodes
17 | are the currencies and the edges are the exchange rates between each currency.
18 | Since our table is complete, the graph is also complete. Then, to solve this
19 | problem, we need to find a cycle whose edge weights product is greater than 1.
20 |
21 | This seems hard to do faster than brute force, so let’s try to reduce it down to
22 | a problem we already know we can solve faster than brute force. (Scroll down if
23 | you want to see exactly how slow brute force is!)
24 |
25 | Here’s a hint: log(a * b) = log(a) + log(b).
26 |
27 | If we take the negative log of the edge weights, the problem of finding a
28 | cumulative product that’s greater than 1 turns into the problem of finding a
29 | negative sum cycle!
30 |
31 | For example, say we have a weighted edge path a -> b -> c -> d. Since we want to
32 | see if a * b * c * d > 1, we’ll take the negative log of each edge:
33 |
34 | -log(a) -> -log(b) -> -log(c) -> -log(d).
35 |
36 | The total cost of this path will then be
37 |
38 | -(log(a) + log(b) + log(c) + log(d)) = -log(a * b * c * d).
39 |
40 | -log(x) < 0 if x is greater than 1, so that’s why if we have a negative cost
41 | cycle, if means that the product of the weighted edges is bigger than 1.
42 |
43 | The Bellman-Ford algorithm can detect negative cycles. So if we run Bellman-Ford
44 | on our graph and discover one, then that means its corresponding edge weights
45 | multiply out to more than 1, and thus we can perform an arbitrage.
46 |
47 | As a refresher, the Bellman-Ford algorithm is commonly used to find the shortest
48 | path between a source vertex and each of the other vertices. If the graph contains
49 | a negative cycle, however, it can detect it and throw an exception (or, in our
50 | case, return true). The main idea of Bellman-Ford is this:
51 |
52 | Since the longest path in any graph has at most |V| - 1 edges, if we take all
53 | the direct edges from our source node, then we have all the one-edged shortest
54 | paths; once we take edges from there, we have all the two-edged shortest paths;
55 | all the way until |V| - 1 sized paths.
56 |
57 | If, after |V| - 1 iterations of this, we can still find a smaller path, then
58 | there must be a negative cycle in the graph. We can start our algorithm on any
59 | vertex in our graph – since our graph is connected (by virtue of it being complete),
60 | then if there’s a negative cycle in our graph, we’ll find it.
61 | '''
62 | from math import log
63 |
64 | def arbitrage(table):
65 | transformed_graph = [[-log(edge) for edge in row] for row in graph]
66 |
67 | # Pick any source vertex -- we can run Bellman-Ford from any vertex and
68 | # get the right result
69 | source = 0
70 | n = len(transformed_graph)
71 | min_dist = [float('inf')] * n
72 |
73 | min_dist[source] = 0
74 |
75 | # Relax edges |V - 1| times
76 | for i in range(n - 1):
77 | for v in range(n):
78 | for w in range(n):
79 | if min_dist[w] > min_dist[v] + transformed_graph[v][w]:
80 | min_dist[w] = min_dist[v] + transformed_graph[v][w]
81 |
82 | # If we can still relax edges, then we have a negative cycle
83 | for v in range(n):
84 | for w in range(n):
85 | if min_dist[w] > min_dist[v] + transformed_graph[v][w]:
86 | return True
87 |
88 | return False
89 |
90 | '''
91 | Because of the triply-nested for loop, this runs in O(N^3) time, and because
92 | we’re creating a transformed copy of the old graph we’re using O(N^2) space.
93 |
94 | P.S: How slow is brute force? Well, we would have to check every single path in
95 | the graph that starts and ends at the same node, and our graph is complete. For
96 | each node, since our graph is connected, we can have every single permutation of
97 | any number of vertices up to N - 1, so brute force would be on the order of
98 | O(N!) time!
99 | '''
100 |
--------------------------------------------------------------------------------
/Problem 31-60/problem_33.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Microsoft.
3 |
4 | Compute the running median of a sequence of numbers. That is, given a stream of
5 | numbers, print out the median of the list so far on each new element.
6 |
7 | Recall that the median of an even-numbered list is the average of the two middle
8 | numbers.
9 |
10 | For example, given the sequence [2, 1, 5, 7, 2, 0, 5], your algorithm should
11 | print out:
12 |
13 | 2
14 | 1.5
15 | 2
16 | 3.5
17 | 2
18 | 2
19 | 2
20 | '''
21 | from __future__ import division
22 | import heapq
23 | import random
24 |
25 | def median(total_list=None):
26 | '''
27 | Find median of either a stream or a list
28 | Args:
29 | (total_list(list))
30 | Returns:
31 | None
32 | '''
33 | max_heap = []
34 | min_heap = []
35 | if total_list is None: # pass a stream of random integer
36 | for num in random_int():
37 | print 'random int = ' + str(num)
38 | max_heap, min_heap = insert_num(max_heap, min_heap, num)
39 | print_median(max_heap, min_heap)
40 |
41 | else: # pass a list
42 | if not total_list:
43 | print_median(max_heap, min_heap)
44 | return
45 |
46 | for i in xrange(0, len(total_list)):
47 | max_heap, min_heap = insert_num(max_heap, min_heap, total_list[i])
48 | print_median(max_heap, min_heap)
49 |
50 |
51 | def insert_num(max_heap, min_heap, num):
52 | if len(max_heap) == len(min_heap) == 0:
53 | heapq.heappush(max_heap, -num)
54 | elif num < -max_heap[0]:
55 | heapq.heappush(max_heap, -num)
56 | else:
57 | heapq.heappush(min_heap, num)
58 |
59 | return balance_heap(max_heap, min_heap)
60 |
61 |
62 | def balance_heap(max_heap, min_heap):
63 | while abs(len(max_heap) - len(min_heap)) > 1:
64 | if len(max_heap) > len(min_heap):
65 | real_value = -heapq.heappop(max_heap)
66 | heapq.heappush(min_heap, real_value)
67 | else:
68 | value = heapq.heappop(min_heap)
69 | heapq.heappush(max_heap, -value)
70 |
71 | return max_heap, min_heap
72 |
73 |
74 | def print_median(max_heap, min_heap):
75 | print 'max_heap = ' + str(max_heap)
76 | print 'min_heap = ' + str(min_heap)
77 |
78 | if not max_heap and not min_heap:
79 | print 0
80 | return
81 |
82 | if len(max_heap) == len(min_heap):
83 | num = (-max_heap[0] + min_heap[0]) / 2
84 | print int(num) if int(num) == float(num) else num
85 | elif len(max_heap) > len(min_heap):
86 | print -max_heap[0]
87 | else:
88 | print min_heap[0]
89 |
90 |
91 | def random_int():
92 | for i in xrange(10):
93 | yield random.randint(0, 10)
94 |
95 |
96 | def main():
97 | # median([])
98 | # median([2, 1, 5, 7, 2, 0, 5])
99 | median()
100 | # median([-1, -2, 3])
101 |
102 |
103 | if __name__ == '__main__':
104 | main()
105 |
--------------------------------------------------------------------------------
/Problem 31-60/problem_34.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Quora.
3 |
4 | Given a string, find the palindrome that can be made by inserting the fewest
5 | number of characters as possible anywhere in the word. If there is more than
6 | one palindrome of minimum length that can be made, return the lexicographically
7 | earliest one (the first one alphabetically).
8 |
9 | For example, given the string "race", you should return "ecarace", since we can
10 | add three letters to it (which is the smallest amount to make a palindrome).
11 | There are seven other palindromes that can be made from "race" by adding three
12 | letters, but "ecarace" comes first alphabetically.
13 |
14 | As another example, given the string "google", you should return "elgoogle".
15 | '''
16 | '''
17 | Reference:
18 | https://www.geeksforgeeks.org/dynamic-programming-set-28-minimum-insertions-to-form-a-palindrome/
19 |
20 | Recursive Solution:
21 |
22 | The minimum number of insertions in the string str[l…..h] can be given as:
23 | minInsertions(str[l+1…..h-1]) if str[l] is equal to str[h]
24 | min(minInsertions(str[l…..h-1]), minInsertions(str[l+1…..h])) + 1 otherwise
25 |
26 | Dynamic Programming:
27 | If we observe the above approach carefully, we can find that it exhibits
28 | overlapping subproblems.
29 | Suppose we want to find the minimum number of insertions in string “abcde”:
30 |
31 | abcde
32 | / | \
33 | / | \
34 | bcde abcd bcd <- case 3 is discarded as str[l] != str[h]
35 | / | \ / | \
36 | / | \ / | \
37 | cde bcd cd bcd abc bc
38 | / | \ / | \ /|\ / | \
39 | de cd d cd bc c………………….
40 | The substrings (bcd) show that the recursion to be terminated and the recursion
41 | tree cannot originate from there. Substring in the same color indicates
42 | overlapping subproblems.
43 |
44 |
45 |
46 | How to reuse solutions of subproblems?
47 | We can create a table to store results of subproblems so that they can be used
48 | directly if same subproblem is encountered again.
49 |
50 | The below table represents the stored values for the string abcde.
51 |
52 | a b c d e
53 | ----------
54 | 0 1 2 3 4
55 | 0 0 1 2 3
56 | 0 0 0 1 2
57 | 0 0 0 0 1
58 | 0 0 0 0 0
59 | How to fill the table?
60 | The table should be filled in diagonal fashion. For the string abcde, 0….4, the
61 | following should be order in which the table is filled:
62 |
63 | Gap = 1:
64 | (0, 1) (1, 2) (2, 3) (3, 4)
65 |
66 | Gap = 2:
67 | (0, 2) (1, 3) (2, 4)
68 |
69 | Gap = 3:
70 | (0, 3) (1, 4)
71 |
72 | Gap = 4:
73 | (0, 4)
74 | '''
75 |
--------------------------------------------------------------------------------
/Problem 31-60/problem_35.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Google.
3 |
4 | Given an array of strictly the characters 'R', 'G', and 'B', segregate the values
5 | of the array so that all the Rs come first, the Gs come second, and the Bs come
6 | last. You can only swap elements of the array.
7 |
8 | Do this in linear time and in-place.
9 |
10 | For example, given the array ['G', 'B', 'R', 'R', 'B', 'R', 'G'], it should
11 | become ['R', 'R', 'R', 'G', 'G', 'B', 'B'].
12 | '''
13 | '''
14 | Note:
15 | This solution should take advantage of the expected high number of equal value
16 | elements.
17 |
18 | The following solution does at most two passes, and therefore is O(n).
19 |
20 | https://github.com/r1cc4rdo/daily_coding_problem/blob/master/daily_coding_problem_31_35.py#L84
21 | '''
22 | def sort(rgbs):
23 | left_index, right_index = 0, len(rgbs) - 1
24 | while True: # move Rs to front
25 |
26 | while rgbs[left_index] == 'R' and left_index < right_index: # advance to first non R
27 | left_index += 1
28 |
29 | while rgbs[right_index] != 'R' and left_index < right_index: # regress to last R
30 | right_index -= 1
31 |
32 | if left_index >= right_index:
33 | break
34 |
35 | rgbs[left_index], rgbs[right_index] = rgbs[right_index], rgbs[left_index]
36 |
37 | right_index = len(rgbs) - 1
38 | while True: # move Bs to tail
39 |
40 | while rgbs[left_index] != 'B' and left_index < right_index: # advance to first B
41 | left_index += 1
42 |
43 | while rgbs[right_index] == 'B' and left_index < right_index: # regress to last non B
44 | right_index -= 1
45 |
46 | if left_index >= right_index:
47 | break
48 |
49 | rgbs[left_index], rgbs[right_index] = rgbs[right_index], rgbs[left_index]
50 |
51 | return rgbs
52 |
53 |
54 | def main():
55 | print sort(['G', 'B', 'R', 'R', 'B', 'R', 'G'])
56 |
57 |
58 | if __name__ == '__main__':
59 | main()
60 |
--------------------------------------------------------------------------------
/Problem 31-60/problem_36.py:
--------------------------------------------------------------------------------
1 | '''
2 | This problem was asked by Dropbox.
3 |
4 | Given the root to a binary search tree, find the second largest node in the tree.
5 | '''
6 | '''
7 | Note:
8 | https://www.geeksforgeeks.org/second-largest-element-in-binary-search-tree-bst/
9 |
10 | The second largest element is second last element in inorder traversal and second
11 | element in reverse inorder traversal. We traverse given Binary Search Tree in
12 | reverse inorder and keep track of counts of nodes visited. Once the count becomes
13 | 2, we print the node.
14 | '''
15 |
--------------------------------------------------------------------------------
/Problem Descriptions.md:
--------------------------------------------------------------------------------
1 | # Problem Description
2 |
3 | -----
4 | ## Table of Content
5 |
6 | [Problem 1-30](#1-30)
7 | [Problem 31-60](#31-60)
8 |
9 | ## Problem 31-60
10 |
11 | ---
12 | ### Problem 36
13 | This problem was asked by Dropbox.
14 |
15 | Given the root to a binary search tree, find the second largest node in the tree.
16 |
17 | ### Problem 35
18 | This problem was asked by Google.
19 |
20 | Given an array of strictly the characters `'R'`, `'G'`, and `'B'`, segregate the values of the array so that all the Rs come first, the Gs come second, and the Bs come last. You can only swap elements of the array.
21 |
22 | Do this in linear time and in-place.
23 |
24 | For example, given the array `['G', 'B', 'R', 'R', 'B', 'R', 'G']`, it should become `['R', 'R', 'R', 'G', 'G', 'B', 'B']`.
25 |
26 |
27 | ### Problem 34
28 | This problem was asked by Quora.
29 |
30 | Given a string, find the palindrome that can be made by inserting the fewest number of characters as possible anywhere in the word. If there is more than one palindrome of minimum length that can be made, return the lexicographically earliest one (the first one alphabetically).
31 |
32 | For example, given the string `"race"`, you should return `"ecarace"`, since we can add three letters to it (which is the smallest amount to make a palindrome). There are seven other palindromes that can be made from `"race"` by adding three letters, but `"ecarace"` comes first alphabetically.
33 |
34 | As another example, given the string `"google"`, you should return `"elgoogle"`.
35 |
36 | ### Problem 33
37 | This problem was asked by Microsoft.
38 |
39 | Compute the running median of a sequence of numbers. That is, given a stream of numbers, print out the median of the list so far on each new element.
40 |
41 | Recall that the median of an even-numbered list is the average of the two middle numbers.
42 |
43 | For example, given the sequence `[2, 1, 5, 7, 2, 0, 5]`, your algorithm should print out:
44 | ```
45 | 2
46 | 1.5
47 | 2
48 | 3.5
49 | 2
50 | 2
51 | 2
52 | ```
53 |
54 | ### Problem 32
55 | This problem was asked by Jane Street.
56 |
57 | Suppose you are given a table of currency exchange rates, represented as a 2D array. Determine whether there is a possible arbitrage: that is, whether there is some sequence of trades you can make, starting with some amount A of any currency, so that you can end up with some amount greater than A of that currency.
58 |
59 | There are no transaction costs and you can trade fractional quantities.
60 |
61 | ### Problem 31
62 | This problem was asked by Google.
63 |
64 | The edit distance between two strings refers to the minimum number of character insertions, deletions, and substitutions required to change one string to the other. For example, the edit distance between `“kitten”` and `“sitting”` is three: substitute the `“k”` for `“s”`, substitute the `“e”` for `“i”`, and append a `“g”`.
65 |
66 | Given two strings, compute the edit distance between them.
67 |
68 | ----
69 |
70 | ## Problem 1-30
71 |
72 | ----
73 | ### Problem 30
74 | This problem was asked by Facebook.
75 |
76 | You are given an array of non-negative integers that represents a two-dimensional elevation map where each element is unit-width wall and the integer is the height. Suppose it will rain and all spots between two walls get filled up.
77 |
78 | Compute how many units of water remain trapped on the map in `O(N)` time and `O(1)` space.
79 |
80 | For example, given the input `[2, 1, 2]`, we can hold 1 unit of water in the middle.
81 |
82 | Given the input `[3, 0, 1, 3, 0, 5]`, we can hold 3 units in the first index, 2 in the second, and 3 in the fourth index (we cannot hold 5 since it would run off to the left), so we can trap 8 units of water.
83 |
84 | ### Problem 29
85 | This problem was asked by Amazon.
86 |
87 | Run-length encoding is a fast and simple method of encoding strings. The basic idea is to represent repeated successive characters as a single count and character. For example, the string `"AAAABBBCCDAA"` would be encoded as `"4A3B2C1D2A"`.
88 |
89 | Implement run-length encoding and decoding. You can assume the string to be encoded have no digits and consists solely of alphabetic characters. You can assume the string to be decoded is valid.
90 |
91 | ### Problem 28
92 | This problem was asked by Palantir.
93 |
94 | Write an algorithm to justify text. Given a sequence of words and an integer line length `k`, return a list of strings which represents each line, fully justified.
95 |
96 | More specifically, you should have as many words as possible in each line. There should be at least one space between each word. Pad extra spaces when necessary so that each line has exactly length `k`. Spaces should be distributed as equally as possible, with the extra spaces, if any, distributed starting from the left.
97 |
98 | If you can only fit one word on a line, then you should pad the right-hand side with spaces.
99 |
100 | Each word is guaranteed not to be longer than `k`.
101 |
102 | For example, given the list of words `["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]` and `k = 16`, you should return the following:
103 |
104 | ```
105 | ["the quick brown", # 1 extra space on the left
106 | "fox jumps over", # 2 extra spaces distributed evenly
107 | "the lazy dog"] # 4 extra spaces distributed evenly
108 | ```
109 |
110 |
111 | ### Problem 27
112 | This problem was asked by Facebook.
113 |
114 | Given a string of round, curly, and square open and closing brackets, return whether the brackets are balanced (well-formed).
115 |
116 | For example, given the string `"([])[]({})"`, you should return `true`.
117 |
118 | Given the string `"([)]"` or `"((()"`, you should return false.
119 |
120 |
121 | ### Problem 26
122 | This problem was asked by Google.
123 |
124 | Given a singly linked list and an integer `k`, remove the kth
last element from the list. `k` is guaranteed to be smaller than the length of the list.
125 |
126 | The list is very long, so making more than one pass is prohibitively expensive.
127 |
128 | Do this in constant space and in one pass.
129 |
130 | ### Problem 25
131 | This problem was asked by Facebook.
132 |
133 | Implement regular expression matching with the following special characters:
134 |
135 | `. (period)` which matches any single character
136 | `* (asterisk)` which matches zero or more of the preceding element
137 | That is, implement a function that takes in a string and a valid regular expression and returns whether or not the string matches the regular expression.
138 |
139 | For example, given the regular expression `"ra."` and the string `"ray"`, your function should return true. The same regular expression on the string `"raymond"` should return false.
140 |
141 | Given the regular expression `".*at"` and the string `"chat"`, your function should return true. The same regular expression on the string "chats" should return false.
142 |
143 | ### Problem 24
144 | This problem was asked by Google.
145 |
146 | Implement locking in a binary tree. A binary tree node can be locked or unlocked only if all of its descendants or ancestors are not locked.
147 |
148 | Design a binary tree node class with the following methods:
149 |
150 | `is_locked`, which returns whether the node is locked
151 | `lock`, which attempts to lock the node. If it cannot be locked, then it should return false. Otherwise, it should lock it and return true.
152 | `unlock`, which unlocks the node. If it cannot be unlocked, then it should return false. Otherwise, it should unlock it and return true.
153 |
154 | You may augment the node to add parent pointers or any other property you would like. You may assume the class is used in a single-threaded program, so there is no need for actual locks or mutexes. Each method should run in `O(h)`, where `h` is the height of the tree.
155 |
156 | ### Problem 23
157 | This problem was asked by Google.
158 |
159 | You are given an M by N matrix consisting of booleans that represents a board. Each True boolean represents a wall. Each False boolean represents a tile you can walk on.
160 |
161 | Given this matrix, a start coordinate, and an end coordinate, return the minimum number of steps required to reach the end coordinate from the start. If there is no possible path, then return null. You can move up, left, down, and right. You cannot move through walls. You cannot wrap around the edges of the board.
162 |
163 | For example, given the following board:
164 |
165 | ```
166 | [[f, f, f, f],
167 | [t, t, f, t],
168 | [f, f, f, f],
169 | [f, f, f, f]]
170 | ```
171 |
172 | and `start = (3, 0) (bottom left)` and `end = (0, 0) (top left)`, the minimum number of steps required to reach the end is `7`, since we would need to go through `(1, 2)` because there is a wall everywhere else on the second row.
173 |
174 | ### Problem 22
175 | This problem was asked by Microsoft.
176 |
177 | Given a dictionary of words and a string made up of those words (no spaces), return the original sentence in a list. If there is more than one possible reconstruction, return any of them. If there is no possible reconstruction, then return null.
178 |
179 | For example, given the set of words `'quick', 'brown', 'the', 'fox'`, and the string `"thequickbrownfox"`, you should return `['the', 'quick', 'brown', 'fox']`.
180 |
181 | Given the set of words `'bed', 'bath', 'bedbath', 'and', 'beyond'`, and the string `"bedbathandbeyond"`, return either `['bed', 'bath', 'and', 'beyond]` or `['bedbath', 'and', 'beyond']`.
182 |
183 |
184 | ### Problem 21
185 | This problem was asked by Snapchat.
186 |
187 | Given an array of time intervals `(start, end)` for classroom lectures (possibly overlapping), find the minimum number of rooms required.
188 |
189 | For example, given `[(30, 75), (0, 50), (60, 150)]`, you should return 2.
190 |
191 | ### Problem 20
192 | This problem was asked by Google.
193 |
194 | Given two singly linked lists that intersect at some point, find the intersecting node. The lists are non-cyclical.
195 |
196 | For example, given `A = 1 -> 3 -> 7 -> 8 -> 10` and `B = 99 -> 1 -> 8 -> 10`, return the node with value 8.
197 |
198 | In this example, assume nodes with the same value are the exact same node objects.
199 |
200 | Do this in `O(M + N)` time (where M and N are the lengths of the lists) and constant space.
201 |
202 | ### Problem 19
203 | This problem was asked by Facebook.
204 |
205 | A builder is looking to build a row of `N` houses that can be of `K` different colors. He has a goal of minimizing cost while ensuring that no two neighboring houses are of the same color.
206 |
207 | Given an `N by K` matrix where the nth row and kth column represents the cost to build the nth house with kth color, return the minimum cost which achieves this goal.
208 |
209 |
210 | ### Problem 18
211 | This problem was asked by Google.
212 |
213 | Given an array of integers and a number `k`, where `1 <= k <= length` of the array, compute the maximum values of each subarray of length `k`.
214 |
215 | For example, given `array = [10, 5, 2, 7, 8, 7]` and `k = 3`, we should get: `[10, 7, 8, 8]`, since:
216 |
217 | ```
218 | 10 = max(10, 5, 2)
219 | 7 = max(5, 2, 7)
220 | 8 = max(2, 7, 8)
221 | 8 = max(7, 8, 7)
222 | ```
223 |
224 | Do this in `O(n)` time and `O(k)` space. You can modify the input array in-place and you do not need to store the results. You can simply print them out as you compute them.
225 |
226 | ### Problem 17
227 | This problem was asked by Google.
228 |
229 | Suppose we represent our file system by a string in the following manner:
230 |
231 | The string `"dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"` represents:
232 | ```
233 | dir
234 | subdir1
235 | subdir2
236 | file.ext
237 | ```
238 | The directory `dir` contains an empty sub-directory `subdir1` and a sub-directory `subdir2` containing a file `file.ext`.
239 |
240 | The string `"dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"` represents:
241 |
242 | ```
243 | dir
244 | subdir1
245 | file1.ext
246 | subsubdir1
247 | subdir2
248 | subsubdir2
249 | file2.ext
250 | ```
251 |
252 | The directory `dir` contains two sub-directories `subdir1` and `subdir2`. `subdir1` contains a file `file1.ext` and an empty second-level sub-directory `subsubdir1`. `subdir2` contains a second-level sub-directory `subsubdir2` containing a file `file2.ext`.
253 |
254 | We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is `"dir/subdir2/subsubdir2/file2.ext"`, and its length is 32 (not including the double quotes).
255 |
256 | Given a string representing the file system in the above format, return the length of the longest absolute path to a file in the abstracted file system. If there is no file in the system, return 0.
257 |
258 | Note:
259 |
260 | The name of a file contains at least a period and an extension.
261 |
262 | The name of a directory or sub-directory will not contain a period.
263 |
264 | ### Problem 16
265 | This problem was asked by Twitter.
266 |
267 | You run an e-commerce website and want to record the last N order ids in a log. Implement a data structure to accomplish this, with the following API:
268 | ```
269 | record(order_id): adds the order_id to the log
270 | get_last(i): gets the ith last element from the log. i is guaranteed to be smaller than or equal to N.
271 | ```
272 | You should be as efficient with time and space as possible.
273 |
274 | ### Problem 15
275 | This problem was asked by Facebook.
276 |
277 | Given a stream of elements too large to store in memory, pick a random element from the stream with uniform probability.
278 |
279 | ### Problem 14
280 | This problem was asked by Google.
281 |
282 | The area of a circle is defined as πr2
. Estimate π to 3 decimal places using a Monte Carlo method.
283 |
284 | Hint: The basic equation of a circle is x2 + y2 = r2
.
285 |
286 | ### Problem 13
287 | This problem was asked by Amazon.
288 |
289 | Given an integer k and a string s, find the length of the longest substring that contains at most k distinct characters.
290 |
291 | For example, given s = `"abcba"` and k = 2, the longest substring with k distinct characters is `"bcb"`.
292 |
293 | ### Problem 12
294 | This problem was asked by Amazon.
295 |
296 | There exists a staircase with N steps, and you can climb up either 1 or 2 steps at a time. Given N, write a function that returns the number of unique ways you can climb the staircase. The order of the steps matters.
297 |
298 | For example, if N is 4, then there are 5 unique ways:
299 | ```
300 | 1, 1, 1, 1
301 | 2, 1, 1
302 | 1, 2, 1
303 | 1, 1, 2
304 | 2, 2
305 | ```
306 | What if, instead of being able to climb 1 or 2 steps at a time, you could climb any number from a set of positive integers X? For example, if `X = {1, 3, 5}`, you could climb 1, 3, or 5 steps at a time.
307 |
308 | ### Problem 11
309 | This problem was asked by Twitter.
310 |
311 | Implement an autocomplete system. That is, given a query string s and a set of all possible query strings, return all strings in the set that have s as a prefix.
312 |
313 | For example, given the query string de and the set of strings `[dog, deer, deal]`, return `[deer, deal]`.
314 |
315 | Hint: Try preprocessing the dictionary into a more efficient data structure to speed up queries.
316 |
317 | ### Problem 10
318 | This problem was asked by Apple.
319 |
320 | Implement a job scheduler which takes in a function f and an integer n, and calls f after n milliseconds.
321 |
322 | ### Problem 9
323 | This problem was asked by Airbnb.
324 |
325 | Given a list of integers, write a function that returns the largest sum of non-adjacent numbers. Numbers can be 0 or negative.
326 |
327 | For example, [2, 4, 6, 2, 5] should return 13, since we pick 2, 6, and 5. [5, 1, 1, 5] should return 10, since we pick 5 and 5.
328 |
329 | Follow-up: Can you do this in O(N) time and constant space?
330 |
331 | ### Problem 8
332 | This problem was asked by Google.
333 |
334 | A unival tree (which stands for "universal value") is a tree where all nodes under it have the same value.
335 |
336 | Given the root to a binary tree, count the number of unival subtrees.
337 |
338 | For example, the following tree has 5 unival subtrees:
339 | ```
340 | 0
341 | / \
342 | 1 0
343 | / \
344 | 1 0
345 | / \
346 | 1 1
347 | ```
348 |
349 | ### Problem 7
350 | This problem was asked by Facebook.
351 |
352 | Given the mapping a = 1, b = 2, ... z = 26, and an encoded message, count the number of ways it can be decoded.
353 |
354 | For example, the message '111' would give 3, since it could be decoded as 'aaa', 'ka', and 'ak'.
355 |
356 | You can assume that the messages are decodable. For example, '001' is not allowed.
357 |
358 | (Not sure if '10001' is valid)
359 |
360 | > Question: How do deal with 0 if there are any?
361 |
362 | > Let's just assume there is no ZERO in the message;
363 |
364 | ### Problem 6
365 | This problem was asked by Google.
366 |
367 | An XOR linked list is a more memory efficient doubly linked list. Instead of each node holding next and prev fields, it holds a field named both, which is a XOR of the next node and the previous node. Implement a XOR linked list; it has an add(element) which adds the element to the end, and a get(index) which returns the node at index.
368 |
369 | If using a language that has no pointers (such as Python), you can assume you have access to 'get_pointer' and 'dereference_pointer' functions that converts between nodes and memory addresses.
370 |
371 | ### Problem 5
372 | This problem was asked by Jane Street.
373 |
374 | `cons(a, b)` constructs a pair, and `car(pair)` and `cdr(pair)` returns the first and last element of that pair. For example, `car(cons(3, 4))` returns 3, and `cdr(cons(3, 4))` returns 4.
375 |
376 | Given this implementation of cons:
377 | ```
378 | def cons(a, b):
379 | def pair(f):
380 | return f(a, b)
381 | return pair
382 | ```
383 | Implement car and cdr.
384 |
385 | ### Problem 4
386 | This problem was asked by Stripe.
387 |
388 | Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
389 |
390 | For example, the input `[3, 4, -1, 1]` should give 2. The input `[1, 2, 0]` should give 3.
391 |
392 | You can modify the input array in-place.
393 |
394 | Some other thoughts:
395 |
396 | > A naive method to solve this problem is to search all positive integers, starting from 1 in the given array. We may have to search at most n+1 numbers in the given array. So this solution takes O(n^2) in worst case.
397 |
398 | > We can use sorting to solve it in lesser time complexity. We can sort the array in O(nLogn) time. Once the array is sorted, then all we need to do is a linear scan of the array. So this approach takes O(nLogn + n) time which is O(nLogn).
399 |
400 | > We can also use hashing. We can build a hash table of all positive elements in the given array. Once the hash table is built. We can look in the hash table for all positive integers, starting from 1. As soon as we find a number which is not there in hash table, we return it. This approach may take O(n) time on average, but it requires O(n) extra space.
401 |
402 | ### Problem 3
403 | This problem was asked by Google.
404 |
405 | Given the root to a binary tree, implement `serialize(root)`, which serializes the tree into a string, and `deserialize(s)`, which deserializes the string back into the tree.
406 |
407 | For example, given the following Node class
408 | ```
409 | class Node:
410 | def __init__(self, val, left=None, right=None):
411 | self.val = val
412 | self.left = left
413 | self.right = right
414 | ```
415 | The following test should pass:
416 | ```
417 | node = Node('root', Node('left', Node('left.left')), Node('right'))
418 | assert deserialize(serialize(node)).left.left.val == 'left.left'
419 | ```
420 |
421 | ### Problem 2
422 | This problem was asked by Uber.
423 |
424 | Given an array of integers, return a new array such that each element at index `i` of the new array is the product of all the numbers in the original array except the one at `i`.
425 |
426 | For example, if our input was `[1, 2, 3, 4, 5]`, the expected output would be `[120, 60, 40, 30, 24]`. If our input was `[3, 2, 1]`, the expected output would be `[2, 3, 6]`.
427 |
428 | Follow-up: what if you can't use division?
429 |
430 | ### Problem 1
431 | This problem was recently asked by Google.
432 |
433 | Given a list of numbers and a number `k`, return whether any two numbers from the list add up to `k`.
434 |
435 | For example, given `[10, 15, 3, 7]` and `k` of 17, return true since 10 + 7 is 17.
436 |
437 | Bonus: Can you do this in one pass?
438 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Daily Coding Problem
2 | Self-implemented solution for https://dailycodingproblem.com every day.
3 |
4 | Details of the problems, please refer to [problem descriptions](https://github.com/Jedshady/daily-coding-problem/blob/master/Problem%20Descriptions.md)
5 |
--------------------------------------------------------------------------------