-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathe0437.py
130 lines (102 loc) · 3.55 KB
/
e0437.py
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# -*- coding: utf-8 -*-
"""Path Sum iii
You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go
downwards (traveling only from parent nodes to child nodes).
The tree has no more than 1,000 nodes and the values are in the range
-1,000,000 to 1,000,000.
Example:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ | \
3 2 11
/ | \
3 -2 1
Return 3. The paths that sum to 8 are:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
"""
from __future__ import annotations
from functools import reduce
from typing import Generator, Optional, Tuple
from adt.tree import Tree
from adt.zipper import ZipperTree
class PS(object):
"""
prefix sum
"""
@staticmethod
def prefix_sum(arr: Tuple[int]) -> Tuple[int, ...]:
def helper(arr_: Tuple[int], rec: Tuple[int, ...]):
if not arr_:
return rec
else:
return helper(arr_[1:], rec + (rec[-1] + arr_[0], ))
return helper(arr, (0, ))
@staticmethod
def path_sum(arr: Tuple, target: int):
def prefix_sums(arr_pre: Tuple, target: int):
def helper(arr_pre_: Tuple, idx: int, target_: int):
return tuple(
filter(lambda x: arr_pre_[idx] - arr_pre_[x] == target_,
range(idx - 1)))
return reduce(
lambda x, y: x + y,
map(
lambda idx: [(i, idx)
for i in helper(arr_pre, idx, target)],
range(len(arr_pre))))
return prefix_sums(PS.prefix_sum(arr), target)
class NewZipperTree(ZipperTree):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def bottom_iter(self) -> Generator[Optional[NewZipperTree]]:
return filter(lambda t: t.bottom_most,
super(NewZipperTree, self).bfs())
def path_iter(self) -> Generator[Optional[NewZipperTree]]:
t = self
while True:
yield t
if t.top_most:
break
else:
t = t.go_up()
def paths_iter(
self) -> Generator[Optional[Generator[Optional[NewZipperTree]]]]:
bottoms = self.bottom_iter()
return (tr.path_iter() for tr in bottoms)
if __name__ == '__main__':
tr1 = Tree(node=1,
children=(
Tree(
node=2,
children=(Tree(node=5, children=(Tree(node=8), )), ),
),
Tree(node=3, children=(Tree(node=6), )),
Tree(node=4,
children=(Tree(node=7,
children=(Tree(node=9), Tree(node=10),
Tree(node=11))), )),
))
zt1 = NewZipperTree(tree=tr1)
# for i in zt1.bottom_iter():
# print(type(i))
# print(i.tree.node)
# for i in zt1.go_bottomleft().path_iter():
# print(type(i))
# print(i.tree.node)
# for path in zt1.paths_iter():
# print('new path:')
# for zt in path:
# print(zt.tree.node)
# print(PS.path_sum([1, 2, 3, 4, 5], 6))
for path in zt1.paths_iter():
tp = tuple(i.tree.node for i in path)
print('new path:')
print(tp)
print(PS.path_sum(tp, 8))
print([tp[i[0]:i[1]] for i in PS.path_sum(tp, 8)])