├── README.md ├── py ├── dynamic_programming │ ├── all_pairs_shortest_path.py │ ├── largest_sum_subarray.py │ └── longest_palindrome_subsequence.py ├── sort │ ├── quick_sort.py │ ├── heap_sort.py │ ├── merge_sort.py │ └── topological_sort.py ├── graph │ ├── dfs.py │ ├── bfs.py │ ├── island_count.py │ ├── bt_diameter.py │ ├── check_balanced_bt.py │ └── find_path_two_nodes_in_tree.py ├── etc │ ├── longest_substring_k_uniq_ch.py │ ├── longest_palindrome_substring.py │ └── lru_cache.py ├── binary_search │ ├── first_failed_build_ver.py │ └── find_k_rotated_sorted_array.py └── data_structure │ └── trie.py ├── trie.ipynb ├── binary_search.ipynb ├── top_k_frequent_number_in_a_list.ipynb ├── shorten_url.ipynb ├── topological_sort.ipynb └── Invert_Binary_Tree.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # coding_interview 2 | -------------------------------------------------------------------------------- /py/dynamic_programming/all_pairs_shortest_path.py: -------------------------------------------------------------------------------- 1 | """ 2 | Floyd Warshall Algorithm 3 | 4 | 3 5 | +-------+ 6 | | | 7 | | 2 v 8 | (0)<----(3)-------+ 9 | | ^ | 10 | 2 | | 6 | 2 11 | v | | 12 | (1)---->(2)<------+ 13 | 4 14 | 15 | """ 16 | # I is infinity 17 | I = 99999 18 | matrix = [[0,2,I,3], 19 | [I,0,4,I], 20 | [I,I,0,6], 21 | [2,I,2,0]] -------------------------------------------------------------------------------- /py/sort/quick_sort.py: -------------------------------------------------------------------------------- 1 | def quick_sort(input, start, end): 2 | if start >= end: 3 | return 4 | 5 | pivot = end 6 | window = start 7 | i = start 8 | while i < pivot: 9 | if input[i] < input[pivot]: 10 | input[window], input[i] = input[i], input[window] 11 | window += 1 12 | i += 1 13 | input[window], input[pivot] = input[pivot], input[window] 14 | pivot = window 15 | quick_sort(input, start, pivot-1) 16 | quick_sort(input, pivot+1, end) 17 | 18 | input = [4,9,1,2,8,3] 19 | quick_sort(input, 0 ,len(input)-1) 20 | print(input) -------------------------------------------------------------------------------- /py/dynamic_programming/largest_sum_subarray.py: -------------------------------------------------------------------------------- 1 | """ 2 | f([-2,-1,4,1]) = 5 3 | f([-2,-1,4,1,-3,1]) = 5 4 | """ 5 | 6 | def largest_sum_subarray(arr): 7 | l_sum = arr[0] 8 | cur = arr[0] 9 | for i in range(1, len(arr)): 10 | if cur > 0: 11 | cur = cur + arr[i] 12 | else: 13 | cur = arr[i] 14 | 15 | l_sum = max(l_sum, cur) 16 | 17 | return l_sum 18 | 19 | 20 | print( largest_sum_subarray( [-2,-1] ) ) 21 | print( largest_sum_subarray( [-2,-1,4,1] ) ) 22 | print( largest_sum_subarray( [-2,-1,4,1,-3,1] ) ) 23 | print( largest_sum_subarray( [-2,-1,4,1,-1,3] ) ) -------------------------------------------------------------------------------- /py/graph/dfs.py: -------------------------------------------------------------------------------- 1 | """ 2 | 4 3 | / \ 4 | 1 5 5 | / \ \ 6 | 2 3 9 7 | 8 | """ 9 | 10 | vertice = [4,1,5,2,3,9] 11 | adj_list = {} 12 | adj_list[4] = [1,5] 13 | adj_list[1] = [2,3] 14 | adj_list[5] = [9] 15 | adj_list[2] = [] 16 | adj_list[3] = [] 17 | adj_list[9] = [] 18 | 19 | stack = [] 20 | visited = [] 21 | 22 | 23 | def dfs(start): 24 | stack.append(start) 25 | 26 | while len(stack) > 0: 27 | cur = stack.pop() 28 | for neighbor in adj_list[cur]: 29 | if not neighbor in visited: 30 | stack.append(neighbor) 31 | visited.append(cur) 32 | 33 | dfs(4) 34 | 35 | print(visited) -------------------------------------------------------------------------------- /py/graph/bfs.py: -------------------------------------------------------------------------------- 1 | """ 2 | 4 3 | / \ 4 | 1 5 5 | / \ \ 6 | 2 3 9 7 | 8 | """ 9 | 10 | vertice = [4,1,5,2,3,9] 11 | adj_list = {} 12 | adj_list[4] = [1,5] 13 | adj_list[1] = [2,3] 14 | adj_list[5] = [9] 15 | adj_list[2] = [] 16 | adj_list[3] = [] 17 | adj_list[9] = [] 18 | 19 | stack = [] 20 | visited = [] 21 | 22 | 23 | def bfs(start): 24 | stack.append(start) 25 | 26 | while len(stack) > 0: 27 | cur = stack.pop() 28 | for neighbor in adj_list[cur]: 29 | if not neighbor in visited: 30 | stack.insert(0, neighbor) 31 | visited.append(cur) 32 | 33 | bfs(4) 34 | 35 | print(visited) -------------------------------------------------------------------------------- /py/etc/longest_substring_k_uniq_ch.py: -------------------------------------------------------------------------------- 1 | """ 2 | abaydae = 5 3 | abcade = 6 4 | """ 5 | 6 | 7 | def longest_substring(str, k): 8 | log = {} 9 | cur = "" 10 | largest = 0 11 | 12 | for i in range(len(str)): 13 | if not str[i] in log: 14 | log[str[i]] = 1 15 | cur += str[i] 16 | else: 17 | if log[str[i]] == k: 18 | largest = max(largest, len(cur)) 19 | start = cur.find(str[i]) 20 | cur = cur[start+1:] + str[i] 21 | else: 22 | log[str[i]] += 1 23 | cur += str[i] 24 | return max(largest, len(cur)) 25 | 26 | str ="aaaaaaa" 27 | print( longest_substring(str,2) ) 28 | 29 | str ="abaa" 30 | print( longest_substring(str,1) ) -------------------------------------------------------------------------------- /py/sort/heap_sort.py: -------------------------------------------------------------------------------- 1 | def heap_sort(input): 2 | p = (len(input) // 2) - 1 3 | #heapify 4 | while p >= 0: 5 | siftdown(input, p, len(input)-1) 6 | p -= 1 7 | 8 | out = len(input) - 1 9 | while out > 0: 10 | input[0], input[out] = input[out], input[0] 11 | out -= 1 12 | siftdown(input, 0, out) 13 | 14 | def siftdown(arr, p, last): 15 | left = 2*p+1 16 | right = 2*p+2 17 | if left > last: 18 | return 19 | if right > last or arr[left] > arr[right]: 20 | max_node = left 21 | else: 22 | max_node = right 23 | 24 | if arr[max_node] > arr[p]: 25 | arr[max_node], arr[p] = arr[p], arr[max_node] 26 | siftdown(arr, max_node, last) 27 | 28 | 29 | input = [4,3,1,5,7,9] 30 | heap_sort(input) 31 | print(input) -------------------------------------------------------------------------------- /py/sort/merge_sort.py: -------------------------------------------------------------------------------- 1 | def merge_sort(input, start, end): 2 | if start == end: 3 | return 4 | 5 | mid = (start + end) // 2 6 | merge_sort(input, start, mid) 7 | merge_sort(input, mid+1, end) 8 | left = input[start: mid+1] 9 | right = input[mid+1: end+1] 10 | 11 | i,j,k = 0,0,start 12 | 13 | while i < len(left) and j < len(right): 14 | if left[i] < right[j]: 15 | input[k] = left[i] 16 | i += 1 17 | else: 18 | input[k] = right[j] 19 | j += 1 20 | k += 1 21 | 22 | while i < len(left): 23 | input[k] = left[i] 24 | i += 1 25 | k += 1 26 | 27 | while j < len(right): 28 | input[k] = right[j] 29 | j += 1 30 | k += 1 31 | 32 | 33 | input = [4,9,1,2,8,3] 34 | merge_sort(input, 0 ,len(input)-1) 35 | print(input) -------------------------------------------------------------------------------- /py/binary_search/first_failed_build_ver.py: -------------------------------------------------------------------------------- 1 | """ 2 | S,S,S,F,F,F,F,F,F,F 3 | """ 4 | 5 | 6 | def binary_search(input, l, r): 7 | if len(input) < 1: 8 | return -1 9 | 10 | while l < r: 11 | mid = (l + r) // 2 12 | if input[mid] == "F": 13 | r = mid 14 | else: 15 | l = mid + 1 16 | 17 | return l if input[l] == "F" else -1 18 | 19 | 20 | input = ["S", "S", "S", "F", "F", "F", "F", "F", "F", "F"] 21 | idx = binary_search(input, 0 , len(input)-1) 22 | print(idx) 23 | 24 | input = ["F", "F", "F"] 25 | idx = binary_search(input, 0 , len(input)-1) 26 | print(idx) 27 | 28 | input = ["S", "S", "S"] 29 | idx = binary_search(input, 0 , len(input)-1) 30 | print(idx) 31 | 32 | input = ["S"] 33 | idx = binary_search(input, 0 , len(input)-1) 34 | print(idx) 35 | 36 | input = [] 37 | idx = binary_search(input, 0 , len(input)-1) 38 | print(idx) -------------------------------------------------------------------------------- /py/etc/longest_palindrome_substring.py: -------------------------------------------------------------------------------- 1 | """ 2 | f("a") = "a" 3 | f("aa") = "aa" 4 | f("aba") = "aba" 5 | f("abba") = "abba" 6 | f("abcdc") = "cdc" 7 | """ 8 | 9 | 10 | def find_pal(left, right, input): 11 | if right >= len(input): 12 | return "" 13 | if input[left] != input[right]: 14 | return "" 15 | while left >= 0 and right < len(input) and input[left] == input[right]: 16 | left -= 1 17 | right += 1 18 | 19 | return input[left+1:right] 20 | 21 | 22 | def longest_palindrome(input): 23 | if len(input) <= 1: 24 | return input 25 | max_odd = "" 26 | max_even = "" 27 | for idx in range(len(input)): 28 | max_odd = max(max_odd, find_pal(idx, idx, input)) 29 | max_even = max(max_even, find_pal(idx, idx+1, input)) 30 | return max(max_odd, max_even) 31 | 32 | print( longest_palindrome("") ) 33 | print( longest_palindrome("a") ) 34 | print( longest_palindrome("aa") ) 35 | print( longest_palindrome("aba") ) 36 | print( longest_palindrome("abcdc") ) 37 | -------------------------------------------------------------------------------- /py/data_structure/trie.py: -------------------------------------------------------------------------------- 1 | """ 2 | store word in dictionary 3 | search word in dictionary return True if exist 4 | """ 5 | 6 | class Trie: 7 | head = {} 8 | 9 | def add(self, word): 10 | cur = self.head 11 | for ch in word: 12 | if ch not in cur: 13 | cur[ch] = {} 14 | cur = cur[ch] 15 | # item denotes the Trie has this word as item 16 | # if item key doesn't exist Trie doesn't have this word but as path to longer word 17 | cur['*'] = True 18 | 19 | def search(self, word): 20 | cur = self.head 21 | for ch in word: 22 | if ch not in cur: 23 | return False 24 | cur = cur[ch] 25 | 26 | if '*' in cur: 27 | return True 28 | else: 29 | return False 30 | 31 | 32 | dictionary = Trie() 33 | 34 | dictionary.add("hi") 35 | dictionary.add("hello") 36 | print(dictionary.search("hi")) 37 | print(dictionary.search("hello")) 38 | print(dictionary.search("hel")) 39 | print(dictionary.search("hey")) -------------------------------------------------------------------------------- /py/graph/island_count.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | 0 0 0 0 1 4 | 1 1 0 0 1 5 | 1 1 0 1 0 6 | 0 0 1 1 0 7 | 0 0 0 0 1 8 | 9 | total 4 islands 10 | 11 | 1 0 0 12 | 0 1 0 13 | 0 1 1 14 | 15 | total 2 islands 16 | 17 | """ 18 | 19 | def adjacency_land(i,j, map): 20 | if i >= 0 and i < len(map) and j >= 0 and j < len(map[0]): 21 | if map[i][j] == 1: 22 | map[i][j] = 0 23 | adjacency_land(i - 1, j, map) 24 | adjacency_land(i + 1, j, map) 25 | adjacency_land(i, j - 1, map) 26 | adjacency_land(i, j + 1, map) 27 | 28 | def island_count(map): 29 | cnt = 0 30 | for i in range(len(map)): 31 | for j in range(len(map[0])): 32 | if map[i][j] == 1: 33 | cnt += 1 34 | map[i][j] = 0 35 | adjacency_land(i-1, j, map) 36 | adjacency_land(i+1, j, map) 37 | adjacency_land(i, j-1, map) 38 | adjacency_land(i, j+1, map) 39 | return cnt 40 | 41 | 42 | map = [ [0,0,0,0,1],[1,1,0,0,1], [1,1,0,1,0], [0,0,1,1,0], [0,0,0,0,1]] 43 | print(island_count(map)) 44 | 45 | map = [ [1,0,0],[0,1,0], [0,1,1]] 46 | print(island_count(map)) -------------------------------------------------------------------------------- /py/dynamic_programming/longest_palindrome_subsequence.py: -------------------------------------------------------------------------------- 1 | # Returns the length of the longest palindromic subsequence 2 | 3 | def longest_palindrome_subsequence(str): 4 | n = len(str) 5 | 6 | # Create a table to store results of subproblems 7 | matrix = [] 8 | for i in range(n): 9 | matrix.append([0]*n) 10 | 11 | # Strings of length 1 are palindrome of length 1 12 | for i in range(n): 13 | matrix[i][i] = 1 14 | 15 | # window is length of substring 16 | for window in range(2, n + 1): 17 | for i in range(n - window + 1): 18 | j = i + window - 1 19 | if str[i] == str[j] and window == 2: 20 | matrix[i][j] = 2 21 | elif str[i] == str[j]: 22 | matrix[i][j] = matrix[i + 1][j - 1] + 2 23 | else: 24 | matrix[i][j] = max(matrix[i][j - 1], matrix[i + 1][j]); 25 | 26 | return matrix[0][n - 1] 27 | 28 | print(longest_palindrome_subsequence("a")) 29 | print(longest_palindrome_subsequence("abba")) 30 | print(longest_palindrome_subsequence("efet")) 31 | print(longest_palindrome_subsequence("abcdcba")) 32 | print(longest_palindrome_subsequence("abcddcba")) 33 | print(longest_palindrome_subsequence("awbcdedcba")) -------------------------------------------------------------------------------- /py/graph/bt_diameter.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 3 | /\ 4 | 2 5 5 | / \ 6 | 9 10 7 | 8 | diameter = 5 9 | 10 | 3 11 | /\ 12 | 2 5 13 | / \ \ 14 | 9 8 10 15 | \ 16 | 4 17 | 18 | diameter = 6 19 | 20 | """ 21 | 22 | 23 | class Node: 24 | def __init__(self, item): 25 | self.val = item 26 | self.left = None 27 | self.right = None 28 | 29 | 30 | def diameter(node): 31 | if not node: 32 | return 0 33 | left_diameter = longest_path(node.left) 34 | right_diameter = longest_path(node.right) 35 | return left_diameter + right_diameter + 1 36 | 37 | 38 | def longest_path(node): 39 | if not node: 40 | return 0 41 | 42 | left = longest_path(node.left) 43 | right = longest_path(node.right) 44 | 45 | return max(left, right) + 1 46 | 47 | 48 | head = Node(3) 49 | head.left = Node(2) 50 | head.right = Node(5) 51 | head.left.left = Node(9) 52 | head.right.right = Node(10) 53 | 54 | print(diameter(head)) 55 | 56 | head = Node(3) 57 | head.left = Node(2) 58 | head.right = Node(5) 59 | head.left.left = Node(9) 60 | head.left.right = Node(8) 61 | head.right.right = Node(10) 62 | head.left.right.right = Node(4) 63 | 64 | print(diameter(head)) 65 | 66 | print(diameter(None)) 67 | print(diameter(Node(10))) -------------------------------------------------------------------------------- /py/sort/topological_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | In Directed Acyclic Graph (DAG), when A->B, A must comes before B in the ordering. 3 | Implement topology sort to visit all vertice in the graph 4 | 5 | a ---> d ---> e <--- c 6 | ^ 7 | | 8 | b 9 | 10 | """ 11 | 12 | from collections import defaultdict 13 | 14 | # store edge information in adjacency list 15 | adjacency_list = defaultdict() 16 | adjacency_list['a'] = ['d'] 17 | adjacency_list['b'] = ['d'] 18 | adjacency_list['c'] = ['e'] 19 | adjacency_list['d'] = ['e'] 20 | adjacency_list['e'] = [] 21 | 22 | # store visited vertex information in visited_list 23 | visited_list = defaultdict() 24 | visited_list['a'] = False 25 | visited_list['b'] = False 26 | visited_list['c'] = False 27 | visited_list['d'] = False 28 | visited_list['e'] = False 29 | 30 | output_stack = [] 31 | 32 | ''' 33 | once visit vertex, change visited_list value to True so we don't revisit it again. 34 | recursively run topology sort to the neighbors in adjacency list. 35 | once all the neighbors are visited, put the current vertex in the output stack. 36 | ''' 37 | 38 | 39 | def topology_sort(vertex): 40 | if not visited_list[vertex]: 41 | visited_list[vertex] = True 42 | for neighbor in adjacency_list[vertex]: 43 | topology_sort(neighbor) 44 | output_stack.insert(0, vertex) 45 | 46 | for vertex in visited_list: 47 | topology_sort(vertex) 48 | 49 | print(output_stack) -------------------------------------------------------------------------------- /py/graph/check_balanced_bt.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 3 | / \ 4 | 2 5 5 | 6 | balanced = True 7 | 8 | 3 9 | / \ 10 | 2 5 11 | / \ 12 | 9 8 13 | \ 14 | 4 15 | 16 | balanced = False 17 | 18 | 3 19 | /\ 20 | 2 5 21 | / \ \ 22 | 9 8 10 23 | \ 24 | 4 25 | 26 | balanced = True 27 | 28 | """ 29 | 30 | 31 | class Node: 32 | def __init__(self, item): 33 | self.val = item 34 | self.left = None 35 | self.right = None 36 | 37 | 38 | def get_depth(node): 39 | if not node: 40 | return 0 41 | 42 | left = get_depth(node.left) 43 | right = get_depth(node.right) 44 | 45 | if left == -1 or right == -1: 46 | return -1 47 | else: 48 | if abs(left - right) > 1: 49 | return -1 50 | else: 51 | return max(left, right)+1 52 | 53 | 54 | def check_balanced_bt(node): 55 | if not node: 56 | return True 57 | 58 | if get_depth(node) == -1: 59 | return False 60 | else: 61 | return True 62 | 63 | head = Node(3) 64 | head.left = Node(2) 65 | head.right = Node(5) 66 | head.right.right = Node(6) 67 | 68 | print(check_balanced_bt(head)) 69 | 70 | head = Node(3) 71 | head.left = Node(2) 72 | head.right = Node(5) 73 | head.right.right = Node(6) 74 | head.right.right.right = Node(6) 75 | 76 | print(check_balanced_bt(head)) -------------------------------------------------------------------------------- /py/graph/find_path_two_nodes_in_tree.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 3 | /\ 4 | 2 5 5 | / \ \ 6 | 9 8 10 7 | \ 8 | 4 9 | 10 | (9,4) : 9-2-8-4 11 | (4,10) : 4-8-2-3-5-10 12 | """ 13 | 14 | class Node: 15 | def __init__(self, item): 16 | self.val = item 17 | self.left = None 18 | self.right = None 19 | 20 | 21 | def print_tree(cur): 22 | if cur.left: 23 | print_tree(cur.left) 24 | print(cur.val) 25 | if cur.right: 26 | print_tree(cur.right) 27 | 28 | 29 | def find_node(cur, target, path): 30 | if not cur: 31 | return [] 32 | 33 | if cur.val == target: 34 | return path + [cur] 35 | else: 36 | lpath = find_node(cur.left, target, path + [cur]) 37 | rpath = find_node(cur.right, target, path + [cur]) 38 | 39 | if lpath is None and rpath is None: 40 | return [] 41 | if lpath: 42 | return lpath 43 | if rpath: 44 | return rpath 45 | 46 | def find_path(tree, n1, n2): 47 | # find first node 48 | n1_path = find_node(tree, n1, []) 49 | ans = [] 50 | if not n1_path: 51 | return None 52 | else: 53 | n1_path = n1_path[::-1] 54 | 55 | for idx, cur in enumerate(n1_path): 56 | n2_path = find_node(cur, n2, []) 57 | if n2_path: 58 | ans = n1_path[:idx]+n2_path 59 | break 60 | 61 | return ans 62 | 63 | head = Node(3) 64 | head.left = Node(2) 65 | head.right = Node(5) 66 | head.left.left = Node(9) 67 | head.left.right = Node(8) 68 | head.right.right = Node(10) 69 | head.left.right.right = Node(4) 70 | 71 | 72 | print([node.val for node in find_path(head, 9, 4)]) 73 | print([node.val for node in find_path(head, 4, 10)]) 74 | print([node.val for node in find_path(head, 4, 4)]) 75 | print([node.val for node in find_path(head, 4, 99)]) 76 | 77 | -------------------------------------------------------------------------------- /py/etc/lru_cache.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self,k,v): 3 | self.key = k 4 | self.val = v 5 | self.prev = None 6 | self.next = None 7 | 8 | 9 | class LRU: 10 | def __init__(self, capacity): 11 | self.capacity = capacity 12 | self.dict = {} 13 | self.head = Node(0,0) 14 | self.tail = Node(0,0) 15 | self.head.next = self.tail 16 | self.tail.prev = self.head 17 | 18 | def remove_node(self, node): 19 | prev = node.prev 20 | next = node.next 21 | prev.next = next 22 | next.prev = prev 23 | 24 | def add_node(self, node): 25 | prev = self.tail.prev 26 | prev.next = node 27 | node.prev = prev 28 | node.next = self.tail 29 | self.tail.prev = node 30 | 31 | def get(self, k): 32 | if k in self.dict: 33 | return self.dict[k].val 34 | else: 35 | return -1 36 | 37 | def put(self, k, v): 38 | if k in self.dict: 39 | node = Node(k,v) 40 | self.remove_node(self.dict[k]) 41 | self.dict[k] = node 42 | self.add_node(node) 43 | else: 44 | if len(self.dict) >= self.capacity: 45 | first = self.head.next 46 | second = self.head.next.next 47 | self.head.next = second 48 | second.prev = self.head 49 | del dict[first.key] 50 | 51 | node = Node(k, v) 52 | self.dict[k] = node 53 | self.add_node(node) 54 | 55 | 56 | def status(self): 57 | cur = self.head 58 | while cur: 59 | print(cur.val) 60 | cur = cur.next 61 | 62 | cache = LRU(3) 63 | cache.put(1,1) 64 | cache.put(2,2) 65 | cache.put(3,3) 66 | cache.put(3,3) 67 | #cache.put(2,2) 68 | cache.status() 69 | print(cache.get(1)) 70 | print(cache.get(2)) 71 | print(cache.get(3)) 72 | print(cache.get(4)) -------------------------------------------------------------------------------- /py/binary_search/find_k_rotated_sorted_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | [1,2,3,4,5] k=4, return 3 3 | [1,2,3,4,5] k=6, return -1 4 | [4,5,1,2,3] k=4, return 0 5 | """ 6 | 7 | def find_pivot(arr,l, r): 8 | if len(arr) < 1: 9 | return -1 10 | if arr[l] < arr[r]: 11 | return -1 12 | 13 | while l < r: 14 | mid = (l + r) // 2 15 | if arr[mid] < arr[mid-1]: 16 | return mid -1 17 | else: 18 | if arr[mid] > arr[l]: 19 | l = mid 20 | else: 21 | r = mid - 1 22 | return l 23 | 24 | 25 | def find_k(arr, pivot, k): 26 | if arr[pivot] == k : 27 | return pivot 28 | 29 | if pivot == -1: 30 | #binary search on arr 31 | l, r = 0, len(arr)-1 32 | elif pivot == 0: 33 | l, r = pivot+1, len(arr)-1 34 | else: 35 | #binary search considering pivot 36 | if k >= arr[0] and k < arr[pivot]: 37 | l, r = 0, pivot-1 38 | else: 39 | l, r = pivot+1, len(arr)-1 40 | 41 | while l < r: 42 | mid = (l + r) // 2 43 | if arr[mid] == k: 44 | return mid 45 | else: 46 | if arr[mid] < k: 47 | l = mid + 1 48 | else: 49 | r = mid - 1 50 | 51 | return l if arr[l] == k else -1 52 | 53 | 54 | arr = [5,1,2,3,4] 55 | pivot = find_pivot(arr, 0 ,len(arr)-1) 56 | #print(pivot) 57 | #print(find_k(arr, pivot, 4)) 58 | 59 | 60 | arr = [4,5,1,2,3] 61 | pivot = find_pivot(arr, 0 ,len(arr)-1) 62 | #print(pivot) 63 | #print(find_k(arr, pivot, 4)) 64 | 65 | 66 | arr = [3,4,5,1,2] 67 | pivot = find_pivot(arr, 0 ,len(arr)-1) 68 | #print(pivot) 69 | #print(find_k(arr, pivot, 4)) 70 | 71 | arr = [2,3,4,5,1] 72 | pivot = find_pivot(arr, 0 ,len(arr)-1) 73 | #print(pivot) 74 | #print(find_k(arr, pivot, 4)) 75 | 76 | arr = [1,2,3,4,5] 77 | pivot = find_pivot(arr, 0 ,len(arr)-1) 78 | #print(pivot) 79 | #print(find_k(arr, pivot, 4)) 80 | 81 | arr = [1,2,3,4,5] 82 | pivot = find_pivot(arr, 0 ,len(arr)-1) 83 | print(pivot) 84 | print(find_k(arr, pivot, 40)) -------------------------------------------------------------------------------- /trie.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Trie\n", 8 | "store word in dictionary \n", 9 | "search word in dictionary return True if exist\n", 10 | "\n", 11 | "Time Complexity: \n", 12 | "Insert: O(key_length) \n", 13 | "search: O(key_length)" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 2, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "class Trie:\n", 23 | " head = {}\n", 24 | "\n", 25 | " def add(self, word):\n", 26 | " cur = self.head\n", 27 | " for ch in word:\n", 28 | " if ch not in cur:\n", 29 | " cur[ch] = {}\n", 30 | " cur = cur[ch]\n", 31 | " # * denotes the Trie has this word as item\n", 32 | " # if * doesn't exist, Trie doesn't have this word but as a path to longer word\n", 33 | " cur['*'] = True\n", 34 | "\n", 35 | " def search(self, word):\n", 36 | " cur = self.head\n", 37 | " for ch in word:\n", 38 | " if ch not in cur:\n", 39 | " return False\n", 40 | " cur = cur[ch]\n", 41 | "\n", 42 | " if '*' in cur:\n", 43 | " return True\n", 44 | " else:\n", 45 | " return False" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 3, 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "name": "stdout", 55 | "output_type": "stream", 56 | "text": [ 57 | "True\n", 58 | "True\n", 59 | "False\n", 60 | "False\n" 61 | ] 62 | } 63 | ], 64 | "source": [ 65 | "dictionary = Trie()\n", 66 | "\n", 67 | "dictionary.add(\"hi\")\n", 68 | "dictionary.add(\"hello\")\n", 69 | "print(dictionary.search(\"hi\"))\n", 70 | "print(dictionary.search(\"hello\"))\n", 71 | "print(dictionary.search(\"hel\"))\n", 72 | "print(dictionary.search(\"hey\"))" 73 | ] 74 | } 75 | ], 76 | "metadata": { 77 | "kernelspec": { 78 | "display_name": "Python 3", 79 | "language": "python", 80 | "name": "python3" 81 | }, 82 | "language_info": { 83 | "codemirror_mode": { 84 | "name": "ipython", 85 | "version": 3 86 | }, 87 | "file_extension": ".py", 88 | "mimetype": "text/x-python", 89 | "name": "python", 90 | "nbconvert_exporter": "python", 91 | "pygments_lexer": "ipython3", 92 | "version": "3.6.4" 93 | } 94 | }, 95 | "nbformat": 4, 96 | "nbformat_minor": 2 97 | } 98 | -------------------------------------------------------------------------------- /binary_search.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Binary Search\n", 8 | "Let's suppose you are running automatic build system. \n", 9 | "[S, S ,S, F, F, F, F] (S: build success, F: build failed) \n", 10 | "this example shows one developer pushed bad code after third build, and \n", 11 | "we can see build failure from fourth build.\n", 12 | "\n", 13 | "Find first failed build in time complexity O(log N)" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 1, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "def binary_search(input, l, r):\n", 23 | " if len(input) < 1:\n", 24 | " return -1\n", 25 | "\n", 26 | " while l < r:\n", 27 | " mid = (l + r) // 2\n", 28 | " if input[mid] == \"F\":\n", 29 | " r = mid\n", 30 | " else:\n", 31 | " l = mid + 1\n", 32 | "\n", 33 | " return l if input[l] == \"F\" else -1" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 2, 39 | "metadata": {}, 40 | "outputs": [ 41 | { 42 | "name": "stdout", 43 | "output_type": "stream", 44 | "text": [ 45 | "3\n", 46 | "0\n", 47 | "-1\n", 48 | "-1\n", 49 | "-1\n" 50 | ] 51 | } 52 | ], 53 | "source": [ 54 | "input = [\"S\", \"S\", \"S\", \"F\", \"F\", \"F\", \"F\", \"F\", \"F\", \"F\"]\n", 55 | "idx = binary_search(input, 0 , len(input)-1)\n", 56 | "print(idx)\n", 57 | "\n", 58 | "input = [\"F\", \"F\", \"F\"]\n", 59 | "idx = binary_search(input, 0 , len(input)-1)\n", 60 | "print(idx)\n", 61 | "\n", 62 | "input = [\"S\", \"S\", \"S\"]\n", 63 | "idx = binary_search(input, 0 , len(input)-1)\n", 64 | "print(idx)\n", 65 | "\n", 66 | "input = [\"S\"]\n", 67 | "idx = binary_search(input, 0 , len(input)-1)\n", 68 | "print(idx)\n", 69 | "\n", 70 | "input = []\n", 71 | "idx = binary_search(input, 0 , len(input)-1)\n", 72 | "print(idx)" 73 | ] 74 | } 75 | ], 76 | "metadata": { 77 | "kernelspec": { 78 | "display_name": "Python 3", 79 | "language": "python", 80 | "name": "python3" 81 | }, 82 | "language_info": { 83 | "codemirror_mode": { 84 | "name": "ipython", 85 | "version": 3 86 | }, 87 | "file_extension": ".py", 88 | "mimetype": "text/x-python", 89 | "name": "python", 90 | "nbconvert_exporter": "python", 91 | "pygments_lexer": "ipython3", 92 | "version": "3.6.4" 93 | } 94 | }, 95 | "nbformat": 4, 96 | "nbformat_minor": 2 97 | } 98 | -------------------------------------------------------------------------------- /top_k_frequent_number_in_a_list.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Top k frequent numbers in a list" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Let's suppose you are rolling a 6 sided dice and put the result in a list. \n", 15 | "ex) [3,2,3,1,2,5,3,6,2,4] is the results when you rolled dice 10 times. \n", 16 | "\n", 17 | "if k=2, we want top 2 frequent numbers in a list, since 3 and 2 are top 2 frequent numbers, \n", 18 | "the return value for this example is [2,3].\n", 19 | "\n", 20 | "when result has same frequent numbers in top k \n", 21 | "such as [1,1,1,2,2,3,3,4,4] when k=3, you can return any same frequent number. \n", 22 | "ex) k=3, return can be [1,2,3] or [1,2,4]\n", 23 | "\n", 24 | "return list must have item from top frequent number to lower frequent number." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 11, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "def top_k_frequent_number(nums,k):\n", 34 | " num_map = {1:0, 2:0,3:0,4:0,5:0,6:0}\n", 35 | "\n", 36 | " for num in nums:\n", 37 | " num_map[num] += 1\n", 38 | "\n", 39 | " ret = []\n", 40 | " while k > 0:\n", 41 | " max_freq = 0\n", 42 | " max_key = 0\n", 43 | " for key in num_map:\n", 44 | " if num_map[key] > max_freq:\n", 45 | " max_freq = num_map[key]\n", 46 | " max_key = key\n", 47 | " ret.append(max_key)\n", 48 | " del num_map[max_key]\n", 49 | " k -= 1\n", 50 | " return ret" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 12, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "[2, 3]\n" 63 | ] 64 | } 65 | ], 66 | "source": [ 67 | "print(top_k_frequent_number([3,2,3,1,2,5,3,6,2,4],2))" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 21, 73 | "metadata": {}, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "[1, 2, 3]\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "print(top_k_frequent_number([1,1,1,2,2,3,3,4,4],3))" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "# Time Complexity: O(n + 6k) = O(n)\n", 92 | "O(n) from creating dictionary \n", 93 | "O(6k) from finding top k frequent number, while k is less than or equal to 6" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "# Space Complexity: O(6+k+2)\n", 101 | "6 from creating dictionary, k from returning list, 2 from max_freq, max_key " 102 | ] 103 | } 104 | ], 105 | "metadata": { 106 | "kernelspec": { 107 | "display_name": "Python 3", 108 | "language": "python", 109 | "name": "python3" 110 | }, 111 | "language_info": { 112 | "codemirror_mode": { 113 | "name": "ipython", 114 | "version": 3 115 | }, 116 | "file_extension": ".py", 117 | "mimetype": "text/x-python", 118 | "name": "python", 119 | "nbconvert_exporter": "python", 120 | "pygments_lexer": "ipython3", 121 | "version": "3.6.4" 122 | } 123 | }, 124 | "nbformat": 4, 125 | "nbformat_minor": 2 126 | } 127 | -------------------------------------------------------------------------------- /shorten_url.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Implement URL shortner\n", 8 | "how will you implement URL shortner? \n", 9 | "The shorten URL should be unique for any URLs.\n", 10 | "\n", 11 | "ex) https://www.youtube.com/watch?v=rkt34Yt4KIo&list=LLxP77kNgVfiiG6CXZ5WMuAQ -> short_url.com/abcde" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## approach with dictionary\n", 19 | "we can use dictionary (key: original url, value: numeric id). \n", 20 | "when new url comes, we can simply give new id (latest id + 1) which always be unique. \n", 21 | "rather than returning id as shorten url, we apply base 62 encoding so we can compress base10 to base62" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 149, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "class URL_Shortener:\n", 31 | " # suppose, we already have 10 billion urls\n", 32 | " id = 10000000000\n", 33 | " # store url to id in order not to have duplicated url with different id\n", 34 | " url2id = {}\n", 35 | " \n", 36 | " def shorten_url(self, original_url):\n", 37 | " if original_url in self.url2id:\n", 38 | " id = self.url2id[original_url]\n", 39 | " shorten_url = self.encode(id)\n", 40 | " else:\n", 41 | " # store url2id in order not to have duplicated url with different id in the future\n", 42 | " self.url2id[original_url] = self.id\n", 43 | " shorten_url = self.encode(self.id)\n", 44 | " # increase cnt for next url\n", 45 | " self.id += 1\n", 46 | " \n", 47 | " return \"short_url.com/\"+shorten_url\n", 48 | " \n", 49 | " def encode(self, id):\n", 50 | " # base 62 characters\n", 51 | " characters = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n", 52 | " base = len(characters)\n", 53 | " ret = []\n", 54 | " # convert base10 id into base62 id for having alphanumeric shorten url\n", 55 | " while id > 0:\n", 56 | " val = id % base\n", 57 | " ret.append(characters[val])\n", 58 | " id = id // base\n", 59 | " # since ret has reversed order of base62 id, reverse ret before return it\n", 60 | " return \"\".join(ret[::-1])" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 153, 66 | "metadata": {}, 67 | "outputs": [ 68 | { 69 | "name": "stdout", 70 | "output_type": "stream", 71 | "text": [ 72 | "short_url.com/aUKYOA\n", 73 | "short_url.com/aUKYOA\n", 74 | "short_url.com/aUKYOB\n", 75 | "short_url.com/aUKYOC\n", 76 | "short_url.com/aUKYOA\n" 77 | ] 78 | } 79 | ], 80 | "source": [ 81 | "shortener = URL_Shortener()\n", 82 | "print(shortener.shorten_url(\"goooooooooooooogle.com\"))\n", 83 | "print(shortener.shorten_url(\"goooooooooooooogle.com\"))\n", 84 | "print(shortener.shorten_url(\"veryloooooooongurl.com\"))\n", 85 | "print(shortener.shorten_url(\"helllloooooooooooo.com\"))\n", 86 | "print(shortener.shorten_url(\"https://coding_interview.com/questions/183658/replacing-letters-with-number\"))" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "## Time Complexity: O( n * log_62(id) )\n", 94 | "Adding one item to dictionary takes O(1), so if we have n items adding new item takes O(n). \n", 95 | "converting base10 to base62 takes O(log_62(id)). \n", 96 | "therefore time complexity is O( n*log_62(id) )" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "## Space Complexity: O(n)\n", 104 | "since we store original id to id value in url2id dictionary, space complexity is O(n)" 105 | ] 106 | } 107 | ], 108 | "metadata": { 109 | "kernelspec": { 110 | "display_name": "Python 3", 111 | "language": "python", 112 | "name": "python3" 113 | }, 114 | "language_info": { 115 | "codemirror_mode": { 116 | "name": "ipython", 117 | "version": 3 118 | }, 119 | "file_extension": ".py", 120 | "mimetype": "text/x-python", 121 | "name": "python", 122 | "nbconvert_exporter": "python", 123 | "pygments_lexer": "ipython3", 124 | "version": "3.6.4" 125 | } 126 | }, 127 | "nbformat": 4, 128 | "nbformat_minor": 2 129 | } 130 | -------------------------------------------------------------------------------- /topological_sort.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# topology sort\n", 8 | "In Directed Acyclic Graph (DAG), when A->B, A must comes before B in the ordering. \n", 9 | "Implement topology sort to visit all vertice in the graph" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 50, 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "data": { 19 | "text/plain": [ 20 | "'\\na ---> d ---> e <--- c\\n ^\\n |\\n b\\n'" 21 | ] 22 | }, 23 | "execution_count": 50, 24 | "metadata": {}, 25 | "output_type": "execute_result" 26 | } 27 | ], 28 | "source": [ 29 | "\"\"\"\n", 30 | "a ---> d ---> e <--- c\n", 31 | " ^\n", 32 | " |\n", 33 | " b\n", 34 | "\"\"\"" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 40, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "from collections import defaultdict " 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "store edge information in adjacency list" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 41, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "adjacency_list = defaultdict()\n", 60 | "adjacency_list['a'] = ['d']\n", 61 | "adjacency_list['b'] = ['d']\n", 62 | "adjacency_list['c'] = ['e']\n", 63 | "adjacency_list['d'] = ['e']\n", 64 | "adjacency_list['e'] = []" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "store visited vertex information in visited_list" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 43, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "visited_list = defaultdict()\n", 81 | "visited_list['a'] = False\n", 82 | "visited_list['b'] = False\n", 83 | "visited_list['c'] = False\n", 84 | "visited_list['d'] = False\n", 85 | "visited_list['e'] = False" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 46, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "output_stack = []" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "once visit vertex, change visited_list value to True so we don't revisit it again. \n", 102 | "recursively run topology sort to the neighbors in adjacency list. \n", 103 | "once all the neighbors are visited, put the current vertex in the output stack." 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 45, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "def topology_sort(vertex):\n", 113 | " if not visited_list[vertex]:\n", 114 | " visited_list[vertex] = True\n", 115 | " for neighbor in adjacency_list[vertex]:\n", 116 | " topology_sort(neighbor)\n", 117 | " output_stack.insert(0, vertex)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "iterate and run topology sort from the first vertex to last vertex." 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 32, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [ 133 | "for vertex in visited_list:\n", 134 | " topology_sort(vertex)" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 34, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "data": { 144 | "text/plain": [ 145 | "['c', 'b', 'a', 'd', 'e']" 146 | ] 147 | }, 148 | "execution_count": 34, 149 | "metadata": {}, 150 | "output_type": "execute_result" 151 | } 152 | ], 153 | "source": [ 154 | "output_stack" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "# time complexity: \n", 162 | "O(V+E)\n", 163 | "# space complexity: \n", 164 | "2 dictionaries, 1 list required" 165 | ] 166 | } 167 | ], 168 | "metadata": { 169 | "kernelspec": { 170 | "display_name": "Python 3", 171 | "language": "python", 172 | "name": "python3" 173 | }, 174 | "language_info": { 175 | "codemirror_mode": { 176 | "name": "ipython", 177 | "version": 3 178 | }, 179 | "file_extension": ".py", 180 | "mimetype": "text/x-python", 181 | "name": "python", 182 | "nbconvert_exporter": "python", 183 | "pygments_lexer": "ipython3", 184 | "version": "3.6.4" 185 | } 186 | }, 187 | "nbformat": 4, 188 | "nbformat_minor": 2 189 | } 190 | -------------------------------------------------------------------------------- /Invert_Binary_Tree.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/plain": [ 11 | "'\\nInverting Binary Tree below,\\n 1\\n / 2 3\\n / \\\\ / 4 5 6 7\\n\\nOutput will be below binary tree.\\n 1\\n / 3 2\\n / \\\\ / 7 6 5 4\\n\\n------------------------------------\\n\\nInverting Binary Tree below,\\n 1\\n / 2 3\\n / 4 7\\n\\n------------\\nOutput will be below binary tree.\\n 1\\n / 3 2\\n / 7 4\\n\\nTime Complexity: O(n)\\nSpace Complexity: O(1)\\n'" 12 | ] 13 | }, 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "output_type": "execute_result" 17 | } 18 | ], 19 | "source": [ 20 | "\"\"\"\n", 21 | "Inverting Binary Tree below,\n", 22 | " 1\n", 23 | " / \\\n", 24 | " 2 3\n", 25 | " / \\ / \\\n", 26 | "4 5 6 7\n", 27 | "\n", 28 | "Output will be below binary tree.\n", 29 | " 1\n", 30 | " / \\\n", 31 | " 3 2\n", 32 | " / \\ / \\\n", 33 | "7 6 5 4\n", 34 | "\n", 35 | "------------------------------------\n", 36 | "\n", 37 | "Inverting Binary Tree below,\n", 38 | " 1\n", 39 | " / \\\n", 40 | " 2 3\n", 41 | " / \\\n", 42 | "4 7\n", 43 | "\n", 44 | "------------\n", 45 | "Output will be below binary tree.\n", 46 | " 1\n", 47 | " / \\\n", 48 | " 3 2\n", 49 | " / \\\n", 50 | "7 4\n", 51 | "\n", 52 | "Time Complexity: O(n)\n", 53 | "Space Complexity: O(1)\n", 54 | "\"\"\"" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 2, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "class TreeNode:\n", 64 | " def __init__(self, x):\n", 65 | " self.val = x\n", 66 | " self.left = None\n", 67 | " self.right = None" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 3, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "def invertTree(node):\n", 77 | " \"\"\"\n", 78 | " :type node: TreeNode\n", 79 | " :rtype: TreeNode\n", 80 | " \"\"\"\n", 81 | " if node is None:\n", 82 | " return None\n", 83 | "\n", 84 | " node.left, node.right = node.right, node.left\n", 85 | "\n", 86 | " invertTree(node.left)\n", 87 | " invertTree(node.right)\n", 88 | "\n", 89 | " return node" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 4, 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [ 98 | "def printTree(root):\n", 99 | " print(root.val)\n", 100 | " if root.left:\n", 101 | " printTree(root.left)\n", 102 | " if root.right:\n", 103 | " printTree(root.right)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 5, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "1\n", 116 | "3\n", 117 | "7\n", 118 | "6\n", 119 | "2\n", 120 | "5\n", 121 | "4\n" 122 | ] 123 | } 124 | ], 125 | "source": [ 126 | "sample_tree = TreeNode(1)\n", 127 | "sample_tree.left = TreeNode(2)\n", 128 | "sample_tree.right = TreeNode(3)\n", 129 | "sample_tree.left.left = TreeNode(4)\n", 130 | "sample_tree.left.right = TreeNode(5)\n", 131 | "sample_tree.right.left = TreeNode(6)\n", 132 | "sample_tree.right.right = TreeNode(7)\n", 133 | "\n", 134 | "invertTree(sample_tree)\n", 135 | "printTree(sample_tree)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 6, 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "name": "stdout", 145 | "output_type": "stream", 146 | "text": [ 147 | "1\n", 148 | "3\n", 149 | "7\n", 150 | "2\n", 151 | "4\n" 152 | ] 153 | } 154 | ], 155 | "source": [ 156 | "sample_tree = TreeNode(1)\n", 157 | "sample_tree.left = TreeNode(2)\n", 158 | "sample_tree.right = TreeNode(3)\n", 159 | "sample_tree.left.left = TreeNode(4)\n", 160 | "sample_tree.left.right = None\n", 161 | "sample_tree.right.left = None\n", 162 | "sample_tree.right.right = TreeNode(7)\n", 163 | "\n", 164 | "invertTree(sample_tree)\n", 165 | "printTree(sample_tree)" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [] 174 | } 175 | ], 176 | "metadata": { 177 | "kernelspec": { 178 | "display_name": "Python 3", 179 | "language": "python", 180 | "name": "python3" 181 | }, 182 | "language_info": { 183 | "codemirror_mode": { 184 | "name": "ipython", 185 | "version": 3 186 | }, 187 | "file_extension": ".py", 188 | "mimetype": "text/x-python", 189 | "name": "python", 190 | "nbconvert_exporter": "python", 191 | "pygments_lexer": "ipython3", 192 | "version": "3.6.4" 193 | } 194 | }, 195 | "nbformat": 4, 196 | "nbformat_minor": 2 197 | } 198 | --------------------------------------------------------------------------------