-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path__init__.py
More file actions
80 lines (54 loc) · 2.52 KB
/
__init__.py
File metadata and controls
80 lines (54 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from typing import List, Optional, Dict
from datastructures.trees.binary.node import BinaryTreeNode
def rob(nums: List[int]) -> int:
"""Uses a top-down approach using Rolling Window technique where the idea is to only remember what is the maximum
gain at the next three houses from the current position."""
current, previous = 0, 0
for house in nums:
current, previous = max(previous + house, current), current
return current
def rob_iii_recursion(root: Optional[BinaryTreeNode]) -> int:
if not root:
return 0
res = root.data
if root.left:
res += rob_iii_recursion(root.left.left) + rob_iii_recursion(root.left.right)
if root.right:
res += rob_iii_recursion(root.right.left) + rob_iii_recursion(root.right.right)
res = max(res, rob_iii_recursion(root.left) + rob_iii_recursion(root.right))
return res
def rob_iii_dynamic_programming_top_down(root: Optional[BinaryTreeNode]) -> int:
if not root:
return 0
cache: Dict[BinaryTreeNode, int] = {}
def dfs(node: Optional[BinaryTreeNode]) -> int:
if not node:
return 0
if node in cache:
return cache[node]
cache[node] = node.data
if node.left:
cache[node] += dfs(node.left.left) + dfs(node.left.right)
if node.right:
cache[node] += dfs(node.right.left) + dfs(node.right.right)
cache[node] = max(cache[node], dfs(node.left) + dfs(node.right))
return cache[node]
return dfs(root)
def rob_iii_dynamic_programming_bottom_up(root: Optional[BinaryTreeNode]) -> int:
if not root:
return 0
def dfs(node: Optional[BinaryTreeNode]) -> List[int]:
# Empty tree case
if not node:
return [0, 0]
# Recursively calculating the maximum amount that can be robbed from the left subtree of the root
left_subtree = dfs(node.left)
# Recursively calculating the maximum amount that can be robbed from the right subtree of the root
right_subtree = dfs(node.right)
# include_root contains the maximum amount of money that can be robbed with the parent node included
include_root = node.data + left_subtree[1] + right_subtree[1]
# exclude_root contains the maximum amount of money that can be robbed with the parent node excluded
exclude_root = max(left_subtree) + max(right_subtree)
return [include_root, exclude_root]
# Returns maximum value from the pair: [include_root, exclude_root]
return max(dfs(root))