From 1a6a8cd91c45465947664a18c1adab69890c850f Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Mon, 7 Nov 2022 10:37:06 +0400 Subject: [PATCH 1/6] add distribute coins --- .../binary_tree/distribute_coins.py | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 data_structures/binary_tree/distribute_coins.py diff --git a/data_structures/binary_tree/distribute_coins.py b/data_structures/binary_tree/distribute_coins.py new file mode 100644 index 000000000000..5714b0ac6139 --- /dev/null +++ b/data_structures/binary_tree/distribute_coins.py @@ -0,0 +1,129 @@ +""" +Author : Alexander Pantyukhin +Date : November 7, 2022 + +Task: +You are given a tree root of a binary tree with n nodes, where each node has +node.data coins. There are exactly n coins in whole tree. + +In one move, we may choose two adjacent nodes and move one coin from one node +to another. A move may be from parent to child, or from child to parent. + +Return the minimum number of moves required to make every node have exactly one coin. + +Example 1: + + 3 + / \ + 0 0 + +Result: 2 + +Example 2: + + 0 + / \ + 3 0 + +Result 3 + +leetcode: https://leetcode.com/problems/distribute-coins-in-binary-tree/ + +Implementation notes: +User depth-first search approach. + +Let n is the number of nodes in tree +Runtime: O(n) +Space: O(1) +""" + +from __future__ import annotations + +from dataclasses import dataclass +from collections import namedtuple + + +@dataclass +class TreeNode: + data: float + left: TreeNode | None = None + right: TreeNode | None = None + +CoinsDistribResult = namedtuple("CoinsDistribResult", 'moves excess') + +def distributeCoins(root: TreeNode | None) -> int: + """ + >>> distributeCoins(TreeNode(3, TreeNode(0), TreeNode(0))) + 2 + >>> distributeCoins(TreeNode(0, TreeNode(3), TreeNode(0))) + 3 + >>> distributeCoins(TreeNode(0, TreeNode(0), TreeNode(3))) + 3 + >>> distributeCoins(None) + 0 + >>> distributeCoins(TreeNode(0, TreeNode(0), TreeNode(0))) + Traceback (most recent call last): + ... + ValueError: The nodes number should be same as the number of coins + >>> distributeCoins(TreeNode(0, TreeNode(1), TreeNode(1))) + Traceback (most recent call last): + ... + ValueError: The nodes number should be same as the number of coins + """ + + if root is None: + return 0 + + # Validation + def count_nodes(node): + """ + >>> count_nodes(None): + 0 + """ + if node is None: + return 0 + + return count_nodes(node.left) + count_nodes(node.right) + 1 + + def count_coins(node): + """ + >>> count_coins(None): + 0 + """ + if node is None: + return 0 + + return count_coins(node.left) + count_coins(node.right) + node.data + + if count_nodes(root) != count_coins(root): + raise ValueError("The nodes number should be same as the number of coins") + + # Main calculation + def get_distrib(node): + """ + >>> get_distrib(None) + namedtuple("CoinsDistribResult", "0 2") + """ + + if node is None: + return CoinsDistribResult(0, 1) + + left_distrib_moves, left_distrib_excess = get_distrib(node.left) + right_distrib_moves, right_distrib_excess = get_distrib(node.right) + + coins_to_left = 1 - left_distrib_excess + coins_to_right = 1 - right_distrib_excess + + result_moves = left_distrib_moves + right_distrib_moves + \ + abs(coins_to_left) + abs(coins_to_right) + result_excess = node.data - coins_to_left - coins_to_right + + return CoinsDistribResult(result_moves, result_excess) + + return get_distrib(root)[0] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 4adf6106613812a85630757b6ac0bb91d07e864e Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 7 Nov 2022 06:38:35 +0000 Subject: [PATCH 2/6] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 76c7f9dea4e3..8c6e2cf382ea 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -173,6 +173,7 @@ * [Binary Tree Path Sum](data_structures/binary_tree/binary_tree_path_sum.py) * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) * [Diff Views Of Binary Tree](data_structures/binary_tree/diff_views_of_binary_tree.py) + * [Distribute Coins](data_structures/binary_tree/distribute_coins.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) * [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py) * [Is Bst](data_structures/binary_tree/is_bst.py) From ab349bbbf233fbf5690d0796eccc312eaf429e40 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 06:39:56 +0000 Subject: [PATCH 3/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../binary_tree/distribute_coins.py | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/data_structures/binary_tree/distribute_coins.py b/data_structures/binary_tree/distribute_coins.py index 5714b0ac6139..0c23aba4755f 100644 --- a/data_structures/binary_tree/distribute_coins.py +++ b/data_structures/binary_tree/distribute_coins.py @@ -4,7 +4,7 @@ Task: You are given a tree root of a binary tree with n nodes, where each node has -node.data coins. There are exactly n coins in whole tree. +node.data coins. There are exactly n coins in whole tree. In one move, we may choose two adjacent nodes and move one coin from one node to another. A move may be from parent to child, or from child to parent. @@ -39,8 +39,8 @@ from __future__ import annotations -from dataclasses import dataclass from collections import namedtuple +from dataclasses import dataclass @dataclass @@ -49,7 +49,9 @@ class TreeNode: left: TreeNode | None = None right: TreeNode | None = None -CoinsDistribResult = namedtuple("CoinsDistribResult", 'moves excess') + +CoinsDistribResult = namedtuple("CoinsDistribResult", "moves excess") + def distributeCoins(root: TreeNode | None) -> int: """ @@ -107,19 +109,23 @@ def get_distrib(node): if node is None: return CoinsDistribResult(0, 1) - + left_distrib_moves, left_distrib_excess = get_distrib(node.left) right_distrib_moves, right_distrib_excess = get_distrib(node.right) coins_to_left = 1 - left_distrib_excess coins_to_right = 1 - right_distrib_excess - result_moves = left_distrib_moves + right_distrib_moves + \ - abs(coins_to_left) + abs(coins_to_right) + result_moves = ( + left_distrib_moves + + right_distrib_moves + + abs(coins_to_left) + + abs(coins_to_right) + ) result_excess = node.data - coins_to_left - coins_to_right return CoinsDistribResult(result_moves, result_excess) - + return get_distrib(root)[0] From 79475999018fc6766981b82cda72a0368b164f56 Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Mon, 7 Nov 2022 10:44:35 +0400 Subject: [PATCH 4/6] fix review notes --- .../binary_tree/distribute_coins.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/data_structures/binary_tree/distribute_coins.py b/data_structures/binary_tree/distribute_coins.py index 0c23aba4755f..dadfe5589811 100644 --- a/data_structures/binary_tree/distribute_coins.py +++ b/data_structures/binary_tree/distribute_coins.py @@ -53,21 +53,21 @@ class TreeNode: CoinsDistribResult = namedtuple("CoinsDistribResult", "moves excess") -def distributeCoins(root: TreeNode | None) -> int: +def distribute_coins(root: TreeNode | None) -> int: """ - >>> distributeCoins(TreeNode(3, TreeNode(0), TreeNode(0))) + >>> distribute_coins(TreeNode(3, TreeNode(0), TreeNode(0))) 2 - >>> distributeCoins(TreeNode(0, TreeNode(3), TreeNode(0))) + >>> distribute_coins(TreeNode(0, TreeNode(3), TreeNode(0))) 3 - >>> distributeCoins(TreeNode(0, TreeNode(0), TreeNode(3))) + >>> distribute_coins(TreeNode(0, TreeNode(0), TreeNode(3))) 3 - >>> distributeCoins(None) + >>> distribute_coins(None) 0 - >>> distributeCoins(TreeNode(0, TreeNode(0), TreeNode(0))) + >>> distribute_coins(TreeNode(0, TreeNode(0), TreeNode(0))) Traceback (most recent call last): ... ValueError: The nodes number should be same as the number of coins - >>> distributeCoins(TreeNode(0, TreeNode(1), TreeNode(1))) + >>> distribute_coins(TreeNode(0, TreeNode(1), TreeNode(1))) Traceback (most recent call last): ... ValueError: The nodes number should be same as the number of coins @@ -77,7 +77,7 @@ def distributeCoins(root: TreeNode | None) -> int: return 0 # Validation - def count_nodes(node): + def count_nodes(node: TreeNode | None) -> int: """ >>> count_nodes(None): 0 @@ -87,7 +87,7 @@ def count_nodes(node): return count_nodes(node.left) + count_nodes(node.right) + 1 - def count_coins(node): + def count_coins(node: TreeNode | None) -> int: """ >>> count_coins(None): 0 @@ -101,7 +101,7 @@ def count_coins(node): raise ValueError("The nodes number should be same as the number of coins") # Main calculation - def get_distrib(node): + def get_distrib(node: TreeNode | None) -> int: """ >>> get_distrib(None) namedtuple("CoinsDistribResult", "0 2") From f19b5e50ec18d2822a06afed58d429a360e239b9 Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Mon, 7 Nov 2022 10:47:03 +0400 Subject: [PATCH 5/6] fix typehint --- data_structures/binary_tree/distribute_coins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/distribute_coins.py b/data_structures/binary_tree/distribute_coins.py index dadfe5589811..3733ddd9f065 100644 --- a/data_structures/binary_tree/distribute_coins.py +++ b/data_structures/binary_tree/distribute_coins.py @@ -101,7 +101,7 @@ def count_coins(node: TreeNode | None) -> int: raise ValueError("The nodes number should be same as the number of coins") # Main calculation - def get_distrib(node: TreeNode | None) -> int: + def get_distrib(node: TreeNode | None) -> CoinsDistribResult: """ >>> get_distrib(None) namedtuple("CoinsDistribResult", "0 2") From efd6ebe3f391ca3bb071e08fe23586d2d8205b21 Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Mon, 7 Nov 2022 10:49:29 +0400 Subject: [PATCH 6/6] fix type in TreeNode --- data_structures/binary_tree/distribute_coins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/distribute_coins.py b/data_structures/binary_tree/distribute_coins.py index 3733ddd9f065..ea02afc2cea6 100644 --- a/data_structures/binary_tree/distribute_coins.py +++ b/data_structures/binary_tree/distribute_coins.py @@ -45,7 +45,7 @@ @dataclass class TreeNode: - data: float + data: int left: TreeNode | None = None right: TreeNode | None = None