From aefe913a7ced85093379a2c73dc579d312837b72 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Sat, 8 Aug 2020 15:37:09 -0700 Subject: [PATCH 01/15] adding static type checking to basic_binary_tree.py --- .../binary_tree/basic_binary_tree.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 9b6e25d5ec56..e0f0c932b6a1 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -4,13 +4,13 @@ class Node: and left, right pointers. """ - def __init__(self, data): - self.data = data - self.left = None - self.right = None + def __init__(self, data: int): + self.data: int = data + self.left: Node = None + self.right: Node = None -def display(tree): # In Order traversal of the tree +def display(tree: Node): # In Order traversal of the tree if tree is None: return @@ -27,13 +27,13 @@ def display(tree): # In Order traversal of the tree def depth_of_tree( - tree, -): # This is the recursive function to find the depth of binary tree. + tree: Node, +) -> int: # This is the recursive function to find the depth of binary tree. if tree is None: return 0 else: - depth_l_tree = depth_of_tree(tree.left) - depth_r_tree = depth_of_tree(tree.right) + depth_l_tree: int = depth_of_tree(tree.left) + depth_r_tree: int = depth_of_tree(tree.right) if depth_l_tree > depth_r_tree: return 1 + depth_l_tree else: @@ -41,8 +41,8 @@ def depth_of_tree( def is_full_binary_tree( - tree, -): # This function returns that is it full binary tree or not? + tree: Node, +) -> bool: # This function returns that is it full binary tree or not? if tree is None: return True if (tree.left is None) and (tree.right is None): @@ -54,7 +54,7 @@ def is_full_binary_tree( def main(): # Main function for testing. - tree = Node(1) + tree: Node = Node(1) tree.left = Node(2) tree.right = Node(3) tree.left.left = Node(4) From e6766473a2ad8bd9325cc8ae76befce459e551d5 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Sun, 9 Aug 2020 14:40:51 -0700 Subject: [PATCH 02/15] Add static type checking to functions with None return type --- data_structures/binary_tree/basic_binary_tree.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index e0f0c932b6a1..9ac91e6ee928 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -4,13 +4,13 @@ class Node: and left, right pointers. """ - def __init__(self, data: int): + def __init__(self, data: int) -> None: self.data: int = data self.left: Node = None self.right: Node = None -def display(tree: Node): # In Order traversal of the tree +def display(tree: Node) -> None: # In Order traversal of the tree if tree is None: return @@ -53,7 +53,7 @@ def is_full_binary_tree( return False -def main(): # Main function for testing. +def main() -> None: # Main function for testing. tree: Node = Node(1) tree.left = Node(2) tree.right = Node(3) From 6310890c3636921c11114889098f12212ee79ef4 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 10 Aug 2020 14:13:45 -0700 Subject: [PATCH 03/15] Applying code review comments --- .../binary_tree/basic_binary_tree.py | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 9ac91e6ee928..5914962c4752 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -5,9 +5,9 @@ class Node: """ def __init__(self, data: int) -> None: - self.data: int = data - self.left: Node = None - self.right: Node = None + self.data = data + self.left: Optional[Node] = None + self.right: Optional[Node] = None def display(tree: Node) -> None: # In Order traversal of the tree @@ -26,23 +26,27 @@ def display(tree: Node) -> None: # In Order traversal of the tree return -def depth_of_tree( - tree: Node, -) -> int: # This is the recursive function to find the depth of binary tree. +def depth_of_tree(tree: Node,) -> int: + """ + Recursive function that finds the depth of a binary tree. + """ + if tree is None: return 0 else: - depth_l_tree: int = depth_of_tree(tree.left) - depth_r_tree: int = depth_of_tree(tree.right) + depth_l_tree = depth_of_tree(tree.left) + depth_r_tree = depth_of_tree(tree.right) if depth_l_tree > depth_r_tree: return 1 + depth_l_tree else: return 1 + depth_r_tree -def is_full_binary_tree( - tree: Node, -) -> bool: # This function returns that is it full binary tree or not? +def is_full_binary_tree(tree: Node,) -> bool: + """ + Returns True if this is a full binary tree + """ + if tree is None: return True if (tree.left is None) and (tree.right is None): @@ -54,7 +58,7 @@ def is_full_binary_tree( def main() -> None: # Main function for testing. - tree: Node = Node(1) + tree = Node(1) tree.left = Node(2) tree.right = Node(3) tree.left.left = Node(4) From 04391803f3a8188adedf487fe36d0ce7f03a1335 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 10 Aug 2020 21:59:23 -0700 Subject: [PATCH 04/15] Added missing import statement --- data_structures/binary_tree/basic_binary_tree.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 5914962c4752..91961ef2c649 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -1,3 +1,5 @@ +from typing import Optional + class Node: """ This is the Class Node with a constructor that contains data variable to type data From 5005cbcf0d1926e9d241d5fb229c3126070df5f0 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 10 Aug 2020 22:11:07 -0700 Subject: [PATCH 05/15] fix spaciing --- data_structures/binary_tree/basic_binary_tree.py | 1 + 1 file changed, 1 insertion(+) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 91961ef2c649..c9b4aa495287 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -1,5 +1,6 @@ from typing import Optional + class Node: """ This is the Class Node with a constructor that contains data variable to type data From 039cdb3f9087b34e5b5d1a78a939c63047f2f6ea Mon Sep 17 00:00:00 2001 From: kanthuc Date: Tue, 11 Aug 2020 13:29:41 -0700 Subject: [PATCH 06/15] "cleaned up depth_of_tree" --- data_structures/binary_tree/basic_binary_tree.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index c9b4aa495287..5472d0506833 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -34,15 +34,7 @@ def depth_of_tree(tree: Node,) -> int: Recursive function that finds the depth of a binary tree. """ - if tree is None: - return 0 - else: - depth_l_tree = depth_of_tree(tree.left) - depth_r_tree = depth_of_tree(tree.right) - if depth_l_tree > depth_r_tree: - return 1 + depth_l_tree - else: - return 1 + depth_r_tree + return 1 + max(depth_of_tree(tree.left), depth_of_tree(tree.right)) if tree else 0 def is_full_binary_tree(tree: Node,) -> bool: From f1c86afa018476b1c44296ccc59ea2cbc181382b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 11 Aug 2020 23:30:28 +0200 Subject: [PATCH 07/15] Add doctests and then streamline display() and is_full_binary_tree() --- .../binary_tree/basic_binary_tree.py | 77 +++++++++++++------ 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 5472d0506833..5553056750ea 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -3,53 +3,80 @@ class Node: """ - This is the Class Node with a constructor that contains data variable to type data - and left, right pointers. + A Node has data variable and pointers to Nodes to its left and right. """ - def __init__(self, data: int) -> None: self.data = data self.left: Optional[Node] = None self.right: Optional[Node] = None -def display(tree: Node) -> None: # In Order traversal of the tree - - if tree is None: - return - - if tree.left is not None: +def display(tree: Optional[Node]) -> None: # In Order traversal of the tree + """ + >>> root = Node(1) + >>> root.left = Node(0) + >>> root.right = Node(2) + >>> display(root) + 0 + 1 + 2 + >>> display(root.right) + 2 + """ + if tree: display(tree.left) - - print(tree.data) - - if tree.right is not None: + print(tree.data) display(tree.right) - return - -def depth_of_tree(tree: Node,) -> int: +def depth_of_tree(tree: Optional[Node]) -> int: """ - Recursive function that finds the depth of a binary tree. + Recursive function that returns the depth of a binary tree. + + >>> root = Node(0) + >>> depth_of_tree(root) + 1 + >>> root.left = Node(0) + >>> depth_of_tree(root) + 2 + >>> root.right = Node(0) + >>> depth_of_tree(root) + 2 + >>> root.left.right = Node(0) + >>> depth_of_tree(root) + 3 + >>> depth_of_tree(root.left) + 2 """ - return 1 + max(depth_of_tree(tree.left), depth_of_tree(tree.right)) if tree else 0 -def is_full_binary_tree(tree: Node,) -> bool: +def is_full_binary_tree(tree: Node) -> bool: """ Returns True if this is a full binary tree - """ - if tree is None: - return True - if (tree.left is None) and (tree.right is None): + >>> root = Node(0) + >>> is_full_binary_tree(root) + True + >>> root.left = Node(0) + >>> is_full_binary_tree(root) + False + >>> root.right = Node(0) + >>> is_full_binary_tree(root) + True + >>> root.left.left = Node(0) + >>> is_full_binary_tree(root) + False + >>> root.right.right = Node(0) + >>> is_full_binary_tree(root) + False + """ + if not tree: return True - if (tree.left is not None) and (tree.right is not None): + if tree.left and tree.right: return is_full_binary_tree(tree.left) and is_full_binary_tree(tree.right) else: - return False + return not tree.left and not tree.right def main() -> None: # Main function for testing. From 052f40846082782ae76f677e0078a4d9e24295db Mon Sep 17 00:00:00 2001 From: kanthuc Date: Wed, 12 Aug 2020 21:49:03 -0700 Subject: [PATCH 08/15] added static typing to lazy_segment_tree.py --- .../binary_tree/lazy_segment_tree.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 461996b87c26..566b7f7513b8 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -2,21 +2,23 @@ class SegmentTree: - def __init__(self, N): + def __init__(self, N: int) -> None: self.N = N - self.st = [ + self.st: List[int] = [ 0 for i in range(0, 4 * N) ] # approximate the overall size of segment tree with array N - self.lazy = [0 for i in range(0, 4 * N)] # create array to store lazy update - self.flag = [0 for i in range(0, 4 * N)] # flag for lazy update + self.lazy: List[int] = [ + 0 for i in range(0, 4 * N) + ] # create array to store lazy update + self.flag: List[int] = [0 for i in range(0, 4 * N)] # flag for lazy update - def left(self, idx): + def left(self, idx: int) -> int: return idx * 2 - def right(self, idx): + def right(self, idx: int) -> int: return idx * 2 + 1 - def build(self, idx, l, r, A): # noqa: E741 + def build(self, idx: int, l: int, r: int, A: List[int]) -> None: # noqa: E741 if l == r: # noqa: E741 self.st[idx] = A[l - 1] else: @@ -27,7 +29,9 @@ def build(self, idx, l, r, A): # noqa: E741 # update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) # for each update) - def update(self, idx, l, r, a, b, val): # noqa: E741 + def update( + self, idx: int, l: int, r: int, a: int, b: int, val: int + ) -> bool: # noqa: E741 """ update(1, 1, N, a, b, v) for update val v to [a,b] """ @@ -57,7 +61,7 @@ def update(self, idx, l, r, a, b, val): # noqa: E741 return True # query with O(lg N) - def query(self, idx, l, r, a, b): # noqa: E741 + def query(self, idx: int, l: int, r: int, a: int, b: int) -> int: # noqa: E741 """ query(1, 1, N, a, b) for query max of [a,b] """ @@ -78,7 +82,7 @@ def query(self, idx, l, r, a, b): # noqa: E741 q2 = self.query(self.right(idx), mid + 1, r, a, b) return max(q1, q2) - def showData(self): + def showData(self) -> None: showList = [] for i in range(1, N + 1): showList += [self.query(1, 1, self.N, i, i)] From 8682782a070264ea8eb0408e583015f383c22889 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 17 Aug 2020 18:40:56 -0700 Subject: [PATCH 09/15] added missing import statement --- data_structures/binary_tree/lazy_segment_tree.py | 1 + 1 file changed, 1 insertion(+) diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 566b7f7513b8..2f4790382ead 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -1,4 +1,5 @@ import math +from typing import List class SegmentTree: From 15b1f622592e35f691875bc2e5b32592a229f704 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 17 Aug 2020 19:21:02 -0700 Subject: [PATCH 10/15] modified variable names for left and right elements --- .../binary_tree/lazy_segment_tree.py | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 2f4790382ead..e247249bf232 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -19,68 +19,72 @@ def left(self, idx: int) -> int: def right(self, idx: int) -> int: return idx * 2 + 1 - def build(self, idx: int, l: int, r: int, A: List[int]) -> None: # noqa: E741 - if l == r: # noqa: E741 - self.st[idx] = A[l - 1] + def build( + self, idx: int, left_element: int, right_element: int, A: List[int] + ) -> None: + if left_element == right_element: + self.st[idx] = A[left_element - 1] else: - mid = (l + r) // 2 - self.build(self.left(idx), l, mid, A) - self.build(self.right(idx), mid + 1, r, A) + mid = (left_element + right_element) // 2 + self.build(self.left(idx), left_element, mid, A) + self.build(self.right(idx), mid + 1, right_element, A) self.st[idx] = max(self.st[self.left(idx)], self.st[self.right(idx)]) # update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) # for each update) def update( - self, idx: int, l: int, r: int, a: int, b: int, val: int - ) -> bool: # noqa: E741 + self, idx: int, left_element: int, right_element: int, a: int, b: int, val: int + ) -> bool: """ update(1, 1, N, a, b, v) for update val v to [a,b] """ if self.flag[idx] is True: self.st[idx] = self.lazy[idx] self.flag[idx] = False - if l != r: # noqa: E741 + if left_element != right_element: self.lazy[self.left(idx)] = self.lazy[idx] self.lazy[self.right(idx)] = self.lazy[idx] self.flag[self.left(idx)] = True self.flag[self.right(idx)] = True - if r < a or l > b: + if right_element < a or left_element > b: return True - if l >= a and r <= b: # noqa: E741 + if left_element >= a and right_element <= b: self.st[idx] = val - if l != r: # noqa: E741 + if left_element != right_element: self.lazy[self.left(idx)] = val self.lazy[self.right(idx)] = val self.flag[self.left(idx)] = True self.flag[self.right(idx)] = True return True - mid = (l + r) // 2 - self.update(self.left(idx), l, mid, a, b, val) - self.update(self.right(idx), mid + 1, r, a, b, val) + mid = (left_element + right_element) // 2 + self.update(self.left(idx), left_element, mid, a, b, val) + self.update(self.right(idx), mid + 1, right_element, a, b, val) self.st[idx] = max(self.st[self.left(idx)], self.st[self.right(idx)]) return True # query with O(lg N) - def query(self, idx: int, l: int, r: int, a: int, b: int) -> int: # noqa: E741 + def query( + self, idx: int, left_element: int, right_element: int, a: int, b: int + ) -> int: """ query(1, 1, N, a, b) for query max of [a,b] """ if self.flag[idx] is True: self.st[idx] = self.lazy[idx] self.flag[idx] = False - if l != r: # noqa: E741 + if left_element != right_element: self.lazy[self.left(idx)] = self.lazy[idx] self.lazy[self.right(idx)] = self.lazy[idx] self.flag[self.left(idx)] = True self.flag[self.right(idx)] = True - if r < a or l > b: + if right_element < a or left_element > b: return -math.inf - if l >= a and r <= b: # noqa: E741 + if left_element >= a and right_element <= b: return self.st[idx] - mid = (l + r) // 2 - q1 = self.query(self.left(idx), l, mid, a, b) - q2 = self.query(self.right(idx), mid + 1, r, a, b) + mid = (left_element + right_element) // 2 + q1 = self.query(self.left(idx), left_element, mid, a, b) + q2 = self.query(self.right(idx), mid + 1, right_element, a, b) return max(q1, q2) def showData(self) -> None: From fae825f38c17cb54c8f1e356e2241f7384470336 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 17 Aug 2020 20:20:25 -0700 Subject: [PATCH 11/15] added static typing to lowest_common_ancestor.py --- .../binary_tree/lowest_common_ancestor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index f560eaa5ef29..dfd6b2d6db21 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -2,9 +2,9 @@ # https://en.wikipedia.org/wiki/Breadth-first_search import queue +from typing import Tuple, List, Dict - -def swap(a, b): +def swap(a: int, b: int) -> Tuple[int, int]: a ^= b b ^= a a ^= b @@ -12,7 +12,7 @@ def swap(a, b): # creating sparse table which saves each nodes 2^i-th parent -def creatSparse(max_node, parent): +def creatSparse(max_node: int, parent: List[List[int]]) -> List[List[int]]: j = 1 while (1 << j) < max_node: for i in range(1, max_node + 1): @@ -22,7 +22,7 @@ def creatSparse(max_node, parent): # returns lca of node u,v -def LCA(u, v, level, parent): +def LCA(u: int, v: int, level: List[int], parent: List[List[int]]) -> List[List[int]]: # u must be deeper in the tree than v if level[u] < level[v]: u, v = swap(u, v) @@ -45,7 +45,7 @@ def LCA(u, v, level, parent): # sets every nodes direct parent # parent of root node is set to 0 # calculates depth of each node from root node -def bfs(level, parent, max_node, graph, root=1): +def bfs(level: List[int], parent: List[List[int]], max_node: int, graph: Dict[int, int], root=1) -> Tuple[List[int], List[List[int]]]: level[root] = 0 q = queue.Queue(maxsize=max_node) q.put(root) @@ -59,7 +59,7 @@ def bfs(level, parent, max_node, graph, root=1): return level, parent -def main(): +def main() -> None: max_node = 13 # initializing with 0 parent = [[0 for _ in range(max_node + 10)] for _ in range(20)] From a548612a58e69b42269c3a382eb5b21baae89f32 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Mon, 17 Aug 2020 20:22:21 -0700 Subject: [PATCH 12/15] fixed formatting --- data_structures/binary_tree/lowest_common_ancestor.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index dfd6b2d6db21..440be03a6fa1 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -4,6 +4,7 @@ import queue from typing import Tuple, List, Dict + def swap(a: int, b: int) -> Tuple[int, int]: a ^= b b ^= a @@ -45,7 +46,13 @@ def LCA(u: int, v: int, level: List[int], parent: List[List[int]]) -> List[List[ # sets every nodes direct parent # parent of root node is set to 0 # calculates depth of each node from root node -def bfs(level: List[int], parent: List[List[int]], max_node: int, graph: Dict[int, int], root=1) -> Tuple[List[int], List[List[int]]]: +def bfs( + level: List[int], + parent: List[List[int]], + max_node: int, + graph: Dict[int, int], + root=1, +) -> Tuple[List[int], List[List[int]]]: level[root] = 0 q = queue.Queue(maxsize=max_node) q.put(root) From dbff1f4e129d21329ea748d13dfcd57b4c03b84c Mon Sep 17 00:00:00 2001 From: kanthuc Date: Wed, 19 Aug 2020 20:38:18 -0700 Subject: [PATCH 13/15] modified files to meet style guidelines, edited docstrings and added some doctests --- .../binary_tree/lazy_segment_tree.py | 35 ++++++++++---- .../binary_tree/lowest_common_ancestor.py | 47 ++++++++++++------- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index e247249bf232..849f1471fd95 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -5,18 +5,32 @@ class SegmentTree: def __init__(self, N: int) -> None: self.N = N - self.st: List[int] = [ - 0 for i in range(0, 4 * N) - ] # approximate the overall size of segment tree with array N - self.lazy: List[int] = [ - 0 for i in range(0, 4 * N) - ] # create array to store lazy update + # approximate the overall size of segment tree with array N + self.st: List[int] = [0 for i in range(0, 4 * N)] + # create array to store lazy update + self.lazy: List[int] = [0 for i in range(0, 4 * N)] self.flag: List[int] = [0 for i in range(0, 4 * N)] # flag for lazy update def left(self, idx: int) -> int: + """ + >>> left(1) + 2 + >>> left(2) + 4 + >>> left(12) + 24 + """ return idx * 2 def right(self, idx: int) -> int: + """ + >>> left(1) + 3 + >>> left(2) + 5 + >>> left(12) + 25 + """ return idx * 2 + 1 def build( @@ -30,12 +44,13 @@ def build( self.build(self.right(idx), mid + 1, right_element, A) self.st[idx] = max(self.st[self.left(idx)], self.st[self.right(idx)]) - # update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) - # for each update) def update( self, idx: int, left_element: int, right_element: int, a: int, b: int, val: int ) -> bool: """ + update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) + for each update) + update(1, 1, N, a, b, v) for update val v to [a,b] """ if self.flag[idx] is True: @@ -87,7 +102,7 @@ def query( q2 = self.query(self.right(idx), mid + 1, right_element, a, b) return max(q1, q2) - def showData(self) -> None: + def show_data(self) -> None: showList = [] for i in range(1, N + 1): showList += [self.query(1, 1, self.N, i, i)] @@ -105,4 +120,4 @@ def showData(self) -> None: segt.update(1, 1, N, 1, 3, 111) print(segt.query(1, 1, N, 1, 15)) segt.update(1, 1, N, 7, 8, 235) - segt.showData() + segt.show_data() diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 440be03a6fa1..812c51183f82 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -2,18 +2,29 @@ # https://en.wikipedia.org/wiki/Breadth-first_search import queue -from typing import Tuple, List, Dict +from typing import Dict, List, Tuple def swap(a: int, b: int) -> Tuple[int, int]: + """ + Return a tuple (b, a) when given two integers a and b + >>> swap(2,3) + (3,2) + >>> swap(3,4) + (4,3) + >>> swap(67, 12) + (12, 67) + """ a ^= b b ^= a a ^= b return a, b -# creating sparse table which saves each nodes 2^i-th parent -def creatSparse(max_node: int, parent: List[List[int]]) -> List[List[int]]: +def create_sparse(max_node: int, parent: List[List[int]]) -> List[List[int]]: + """ + creating sparse table which saves each nodes 2^i-th parent + """ j = 1 while (1 << j) < max_node: for i in range(1, max_node + 1): @@ -23,7 +34,9 @@ def creatSparse(max_node: int, parent: List[List[int]]) -> List[List[int]]: # returns lca of node u,v -def LCA(u: int, v: int, level: List[int], parent: List[List[int]]) -> List[List[int]]: +def lowest_common_ancestor( + u: int, v: int, level: List[int], parent: List[List[int]] +) -> List[List[int]]: # u must be deeper in the tree than v if level[u] < level[v]: u, v = swap(u, v) @@ -43,16 +56,18 @@ def LCA(u: int, v: int, level: List[int], parent: List[List[int]]) -> List[List[ # runs a breadth first search from root node of the tree -# sets every nodes direct parent -# parent of root node is set to 0 -# calculates depth of each node from root node -def bfs( +def breadth_first_search( level: List[int], parent: List[List[int]], max_node: int, graph: Dict[int, int], root=1, ) -> Tuple[List[int], List[List[int]]]: + """ + sets every nodes direct parent + parent of root node is set to 0 + calculates depth of each node from root node + """ level[root] = 0 q = queue.Queue(maxsize=max_node) q.put(root) @@ -87,14 +102,14 @@ def main() -> None: 12: [], 13: [], } - level, parent = bfs(level, parent, max_node, graph, 1) - parent = creatSparse(max_node, parent) - print("LCA of node 1 and 3 is: ", LCA(1, 3, level, parent)) - print("LCA of node 5 and 6 is: ", LCA(5, 6, level, parent)) - print("LCA of node 7 and 11 is: ", LCA(7, 11, level, parent)) - print("LCA of node 6 and 7 is: ", LCA(6, 7, level, parent)) - print("LCA of node 4 and 12 is: ", LCA(4, 12, level, parent)) - print("LCA of node 8 and 8 is: ", LCA(8, 8, level, parent)) + level, parent = breadth_first_search(level, parent, max_node, graph, 1) + parent = create_sparse(max_node, parent) + print("LCA of node 1 and 3 is: ", lowest_common_ancestor(1, 3, level, parent)) + print("LCA of node 5 and 6 is: ", lowest_common_ancestor(5, 6, level, parent)) + print("LCA of node 7 and 11 is: ", lowest_common_ancestor(7, 11, level, parent)) + print("LCA of node 6 and 7 is: ", lowest_common_ancestor(6, 7, level, parent)) + print("LCA of node 4 and 12 is: ", lowest_common_ancestor(4, 12, level, parent)) + print("LCA of node 8 and 8 is: ", lowest_common_ancestor(8, 8, level, parent)) if __name__ == "__main__": From 1496a2d71d7ad887081da1954046667639e4ab6a Mon Sep 17 00:00:00 2001 From: kanthuc Date: Thu, 20 Aug 2020 13:17:23 -0700 Subject: [PATCH 14/15] added and fixed doctests in lazy_segment_tree.py --- .../binary_tree/lazy_segment_tree.py | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 849f1471fd95..3719189a0d38 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -13,22 +13,24 @@ def __init__(self, N: int) -> None: def left(self, idx: int) -> int: """ - >>> left(1) + >>> segment_tree = SegmentTree(15) + >>> segment_tree.left(1) 2 - >>> left(2) + >>> segment_tree.left(2) 4 - >>> left(12) + >>> segment_tree.left(12) 24 """ return idx * 2 def right(self, idx: int) -> int: """ - >>> left(1) + >>> segment_tree = SegmentTree(15) + >>> segment_tree.right(1) 3 - >>> left(2) + >>> segment_tree.right(2) 5 - >>> left(12) + >>> segment_tree.right(12) 25 """ return idx * 2 + 1 @@ -84,6 +86,15 @@ def query( ) -> int: """ query(1, 1, N, a, b) for query max of [a,b] + >>> A = [1, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8] + >>> segment_tree = SegmentTree(15) + >>> segment_tree.build(1, 1, 15, A) + >>> segment_tree.query(1, 1, 15, 4, 6) + 7 + >>> segment_tree.query(1, 1, 15, 7, 11) + 14 + >>> segment_tree.query(1, 1, 15, 7, 12)) + 15 """ if self.flag[idx] is True: self.st[idx] = self.lazy[idx] From 34cdf3d661b51f729af90ff059d9de4274c79a98 Mon Sep 17 00:00:00 2001 From: kanthuc Date: Thu, 20 Aug 2020 20:10:56 -0700 Subject: [PATCH 15/15] fixed errors in doctests --- data_structures/binary_tree/lazy_segment_tree.py | 2 +- data_structures/binary_tree/lowest_common_ancestor.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 3719189a0d38..66b995fa1733 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -93,7 +93,7 @@ def query( 7 >>> segment_tree.query(1, 1, 15, 7, 11) 14 - >>> segment_tree.query(1, 1, 15, 7, 12)) + >>> segment_tree.query(1, 1, 15, 7, 12) 15 """ if self.flag[idx] is True: diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 812c51183f82..c25536cdaef0 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -9,9 +9,9 @@ def swap(a: int, b: int) -> Tuple[int, int]: """ Return a tuple (b, a) when given two integers a and b >>> swap(2,3) - (3,2) + (3, 2) >>> swap(3,4) - (4,3) + (4, 3) >>> swap(67, 12) (12, 67) """