From 5c091aa81864778f4fff49d9fa771ae1600ffb9e Mon Sep 17 00:00:00 2001 From: jahir-raihan Date: Mon, 2 Oct 2023 13:30:43 +0600 Subject: [PATCH 01/12] Algorithm to get maximum path sum of a binary tree. --- .../binary_tree_maximum_path_sum.py | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 data_structures/binary_tree/binary_tree_maximum_path_sum.py diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py new file mode 100644 index 000000000000..a86e9a2718c8 --- /dev/null +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -0,0 +1,126 @@ +""" +A path in a binary tree is a sequence of nodes where each pair +of adjacent nodes in the sequence has an edge connecting +them. A node can only appear in the sequence at most once. Note +that the path does not need to pass through the root. + +The path sum of a path is the sum of the node's values in the path. + +Given the root of a binary tree, return the maximum path sum of any non-empty path. + +Leetcode Reference : https://leetcode.com/problems/binary-tree-maximum-path-sum/ +""" + + +class TreeNode: + + """ + TreeNode has tree variables, val -> Stores value of the node + left, right -> Stores the pointer to left or right node. + """ + + def __init__(self, val: int, left=None, right=None) -> None: + self.val: int = val + self.left: TreeNode | None = left + self.right: TreeNode | None = right + + +class GetMaxPathSum: + + r""" + + GetMaxPathSum takes root node of a tree as initial argument. + Upon calling max_path_sum(), it returns maximum path + sum from the tree. + + # Test + + The below tree looks like this + 10 + / \ + 5 -3 + / \ \ + 3 2 11 + / \ \ + 3 -2 1 + + Result will be calculated like : 3 -> 3 -> 5 -> 10 -> -3 -> 11 + As it is the maximum path possible. + + + >>> root = TreeNode(10) + >>> root.left = TreeNode(5) + >>> root.right = TreeNode(-3) + >>> root.left.left = TreeNode(3) + >>> root.left.right = TreeNode(2) + >>> root.right.right = TreeNode(11) + >>> root.left.left.left = TreeNode(3) + >>> root.left.left.right = TreeNode(-2) + >>> root.left.right.right = TreeNode(1) + + >>> GetMaxPathSum(root).max_path_sum() + 29 + """ + + def __init__(self, root): + self.sum = -9999999999 + self.root = root + + def traverse(self, root: TreeNode) -> int: + + """ + Returns maximum path sum by recursively taking max_path_sum from left + and max_path_sum from right if current Node has a left or right Node. + + :param root -> tree root: + :return int: + """ + + if root is None: + return 0 + + right_sum = max(self.traverse(root.right), 0) + left_sum = max(self.traverse(root.left), 0) + + val = root.val + right_sum + left_sum + self.sum = max(val, self.sum) + + return root.val + max(right_sum, left_sum) + + def max_path_sum(self) -> int: + + """ + Driver method to get max_path_sum by calling traverse method. + :return max_path_sum: + """ + self.traverse(self.root) + return self.sum + + +def construct_tree() -> TreeNode: + """ + The below tree + -10 + / \ + 9 20 + / \ + 15 7 + """ + + root = TreeNode(-10) + root.left = TreeNode(9) + root.right = TreeNode(20) + root.right.left = TreeNode(15) + root.right.right = TreeNode(7) + return root + + +if __name__ == '__main__': + import doctest + + tree = GetMaxPathSum(construct_tree()) + max_sum = tree.max_path_sum() + + print("Given example output: ", max_sum) + + doctest.testmod() From 969d2a4a45192e61bf702c7ab356a59bad53ebd3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 07:46:20 +0000 Subject: [PATCH 02/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/binary_tree/binary_tree_maximum_path_sum.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index a86e9a2718c8..74f954a35c5d 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -26,7 +26,6 @@ def __init__(self, val: int, left=None, right=None) -> None: class GetMaxPathSum: - r""" GetMaxPathSum takes root node of a tree as initial argument. @@ -67,7 +66,6 @@ def __init__(self, root): self.root = root def traverse(self, root: TreeNode) -> int: - """ Returns maximum path sum by recursively taking max_path_sum from left and max_path_sum from right if current Node has a left or right Node. @@ -88,7 +86,6 @@ def traverse(self, root: TreeNode) -> int: return root.val + max(right_sum, left_sum) def max_path_sum(self) -> int: - """ Driver method to get max_path_sum by calling traverse method. :return max_path_sum: @@ -115,7 +112,7 @@ def construct_tree() -> TreeNode: return root -if __name__ == '__main__': +if __name__ == "__main__": import doctest tree = GetMaxPathSum(construct_tree()) From b238cbb11e37d798384bc903fe674f435de5bc90 Mon Sep 17 00:00:00 2001 From: jahir-raihan Date: Mon, 2 Oct 2023 13:52:16 +0600 Subject: [PATCH 03/12] Added "TreeNode | None" as traverse method argument type hints to accept both --- data_structures/binary_tree/binary_tree_maximum_path_sum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index a86e9a2718c8..a58f414c0e75 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -66,7 +66,7 @@ def __init__(self, root): self.sum = -9999999999 self.root = root - def traverse(self, root: TreeNode) -> int: + def traverse(self, root: TreeNode | None) -> int: """ Returns maximum path sum by recursively taking max_path_sum from left From 3692057162ac6c5a5a295ce46ff6532980d92164 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 07:54:56 +0000 Subject: [PATCH 04/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/binary_tree/binary_tree_maximum_path_sum.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index a86e9a2718c8..74f954a35c5d 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -26,7 +26,6 @@ def __init__(self, val: int, left=None, right=None) -> None: class GetMaxPathSum: - r""" GetMaxPathSum takes root node of a tree as initial argument. @@ -67,7 +66,6 @@ def __init__(self, root): self.root = root def traverse(self, root: TreeNode) -> int: - """ Returns maximum path sum by recursively taking max_path_sum from left and max_path_sum from right if current Node has a left or right Node. @@ -88,7 +86,6 @@ def traverse(self, root: TreeNode) -> int: return root.val + max(right_sum, left_sum) def max_path_sum(self) -> int: - """ Driver method to get max_path_sum by calling traverse method. :return max_path_sum: @@ -115,7 +112,7 @@ def construct_tree() -> TreeNode: return root -if __name__ == '__main__': +if __name__ == "__main__": import doctest tree = GetMaxPathSum(construct_tree()) From dc26a05aa81029d60e210c20bc1dee748e9daa92 Mon Sep 17 00:00:00 2001 From: jahir-raihan Date: Mon, 2 Oct 2023 14:06:05 +0600 Subject: [PATCH 05/12] Added doctest for construct_tree and type hints for TreeNode --- .../binary_tree_maximum_path_sum.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index a86e9a2718c8..72e04429da8c 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -19,10 +19,10 @@ class TreeNode: left, right -> Stores the pointer to left or right node. """ - def __init__(self, val: int, left=None, right=None) -> None: + def __init__(self, val: int) -> None: self.val: int = val - self.left: TreeNode | None = left - self.right: TreeNode | None = right + self.left: TreeNode | None = None + self.right: TreeNode | None = None class GetMaxPathSum: @@ -62,11 +62,11 @@ class GetMaxPathSum: 29 """ - def __init__(self, root): + def __init__(self, root) -> None: self.sum = -9999999999 self.root = root - def traverse(self, root: TreeNode) -> int: + def traverse(self, root: TreeNode | None) -> int: """ Returns maximum path sum by recursively taking max_path_sum from left @@ -98,13 +98,22 @@ def max_path_sum(self) -> int: def construct_tree() -> TreeNode: - """ + r""" The below tree -10 / \ 9 20 / \ 15 7 + + >>> root = TreeNode(-10) + >>> root.left = TreeNode(9) + >>> root.right = TreeNode(20) + >>> root.right.left = TreeNode(15) + >>> root.right.right = TreeNode(7) + + >>> GetMaxPathSum(construct_tree()).max_path_sum() + 42 """ root = TreeNode(-10) From c1575a1a666a4e3604969baa0851f98e30c8a0cc Mon Sep 17 00:00:00 2001 From: jahir-raihan Date: Mon, 2 Oct 2023 14:12:53 +0600 Subject: [PATCH 06/12] Added type hint and doctest --- .../binary_tree_maximum_path_sum.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index a86e9a2718c8..72e04429da8c 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -19,10 +19,10 @@ class TreeNode: left, right -> Stores the pointer to left or right node. """ - def __init__(self, val: int, left=None, right=None) -> None: + def __init__(self, val: int) -> None: self.val: int = val - self.left: TreeNode | None = left - self.right: TreeNode | None = right + self.left: TreeNode | None = None + self.right: TreeNode | None = None class GetMaxPathSum: @@ -62,11 +62,11 @@ class GetMaxPathSum: 29 """ - def __init__(self, root): + def __init__(self, root) -> None: self.sum = -9999999999 self.root = root - def traverse(self, root: TreeNode) -> int: + def traverse(self, root: TreeNode | None) -> int: """ Returns maximum path sum by recursively taking max_path_sum from left @@ -98,13 +98,22 @@ def max_path_sum(self) -> int: def construct_tree() -> TreeNode: - """ + r""" The below tree -10 / \ 9 20 / \ 15 7 + + >>> root = TreeNode(-10) + >>> root.left = TreeNode(9) + >>> root.right = TreeNode(20) + >>> root.right.left = TreeNode(15) + >>> root.right.right = TreeNode(7) + + >>> GetMaxPathSum(construct_tree()).max_path_sum() + 42 """ root = TreeNode(-10) From 49633c2fd2ef00d791cf32bd2e71171aac9e595b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:13:35 +0000 Subject: [PATCH 07/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/binary_tree/binary_tree_maximum_path_sum.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index 72e04429da8c..3ef426940172 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -26,7 +26,6 @@ def __init__(self, val: int) -> None: class GetMaxPathSum: - r""" GetMaxPathSum takes root node of a tree as initial argument. @@ -67,7 +66,6 @@ def __init__(self, root) -> None: self.root = root def traverse(self, root: TreeNode | None) -> int: - """ Returns maximum path sum by recursively taking max_path_sum from left and max_path_sum from right if current Node has a left or right Node. @@ -88,7 +86,6 @@ def traverse(self, root: TreeNode | None) -> int: return root.val + max(right_sum, left_sum) def max_path_sum(self) -> int: - """ Driver method to get max_path_sum by calling traverse method. :return max_path_sum: @@ -124,7 +121,7 @@ def construct_tree() -> TreeNode: return root -if __name__ == '__main__': +if __name__ == "__main__": import doctest tree = GetMaxPathSum(construct_tree()) From cc7db5cdda4d21164214e8d27058cbf8de03987f Mon Sep 17 00:00:00 2001 From: jahir-raihan Date: Mon, 2 Oct 2023 14:16:06 +0600 Subject: [PATCH 08/12] Preformatted using black --- data_structures/binary_tree/binary_tree_maximum_path_sum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index 72e04429da8c..3040fdb2343d 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -124,7 +124,7 @@ def construct_tree() -> TreeNode: return root -if __name__ == '__main__': +if __name__ == "__main__": import doctest tree = GetMaxPathSum(construct_tree()) From 16e7f01a63641549a73ac8f0b8a44fdcb54ffd8b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:20:09 +0000 Subject: [PATCH 09/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/binary_tree/binary_tree_maximum_path_sum.py | 1 - 1 file changed, 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index 09b75ef5f25e..4a35d4ba3217 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -126,4 +126,3 @@ def construct_tree() -> TreeNode: print("Given example output: ", max_sum) doctest.testmod() - From ed46c53e9b368ee22916c5c8bb9fe2a4411e7344 Mon Sep 17 00:00:00 2001 From: jahir-raihan Date: Mon, 2 Oct 2023 16:25:22 +0600 Subject: [PATCH 10/12] Organized imports --- .../binary_tree/binary_tree_maximum_path_sum.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index 09b75ef5f25e..af86877b6c81 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -1,19 +1,9 @@ -""" -A path in a binary tree is a sequence of nodes where each pair -of adjacent nodes in the sequence has an edge connecting -them. A node can only appear in the sequence at most once. Note -that the path does not need to pass through the root. - -The path sum of a path is the sum of the node's values in the path. - -Given the root of a binary tree, return the maximum path sum of any non-empty path. - -Leetcode Reference : https://leetcode.com/problems/binary-tree-maximum-path-sum/ -""" from __future__ import annotations + from dataclasses import dataclass +# Leetcode Reference : https://leetcode.com/problems/binary-tree-maximum-path-sum/ @dataclass class TreeNode: val: int @@ -57,7 +47,7 @@ class GetMaxPathSum: 29 """ - def __init__(self, root) -> None: + def __init__(self, root: TreeNode) -> None: self.sum = -9999999999 self.root = root @@ -126,4 +116,3 @@ def construct_tree() -> TreeNode: print("Given example output: ", max_sum) doctest.testmod() - From ce58eccf6cd65b77eb5641849216fb741e16ad0c Mon Sep 17 00:00:00 2001 From: cclauss Date: Tue, 8 Sep 2026 13:57:41 +0000 Subject: [PATCH 11/12] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 69bdb2b6c9d0..cbbed67b5456 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -251,6 +251,7 @@ * [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py) * [Binary Search Tree](data_structures/binary_tree/binary_search_tree.py) * [Binary Search Tree Recursive](data_structures/binary_tree/binary_search_tree_recursive.py) + * [Binary Tree Maximum Path Sum](data_structures/binary_tree/binary_tree_maximum_path_sum.py) * [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py) * [Binary Tree Node Sum](data_structures/binary_tree/binary_tree_node_sum.py) * [Binary Tree Path Sum](data_structures/binary_tree/binary_tree_path_sum.py) @@ -876,6 +877,7 @@ * [Test Factorial](maths/test_factorial.py) * [Test Prime Check](maths/test_prime_check.py) * [Three Sum](maths/three_sum.py) + * [Tonelli Shanks](maths/tonelli_shanks.py) * [Trailing Zeroes](maths/trailing_zeroes.py) * [Trapezoidal Rule](maths/trapezoidal_rule.py) * [Triplet Sum](maths/triplet_sum.py) From d95f1c364a0459fff24014b538fca67df88d4120 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 8 Sep 2026 17:04:11 +0200 Subject: [PATCH 12/12] Apply suggestion from @cclauss --- .../binary_tree/binary_tree_maximum_path_sum.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_maximum_path_sum.py b/data_structures/binary_tree/binary_tree_maximum_path_sum.py index af86877b6c81..cc8c7a3c2e55 100644 --- a/data_structures/binary_tree/binary_tree_maximum_path_sum.py +++ b/data_structures/binary_tree/binary_tree_maximum_path_sum.py @@ -110,9 +110,7 @@ def construct_tree() -> TreeNode: if __name__ == "__main__": import doctest - tree = GetMaxPathSum(construct_tree()) - max_sum = tree.max_path_sum() - - print("Given example output: ", max_sum) - doctest.testmod() + + tree = GetMaxPathSum(construct_tree()) + print(f"{tree.max_path_sum() = }")