-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathbalanced-k-factor-decomposition.py
More file actions
119 lines (105 loc) · 3.27 KB
/
balanced-k-factor-decomposition.py
File metadata and controls
119 lines (105 loc) · 3.27 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
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
# Time: precompute: O(rlogr)
# runtime: O(k * (logn)^(k - 1))
# Space: O(rlogr)
import bisect
# backtracking, number theory
def factors(n):
result = [[] for _ in xrange(n+1)]
for i in xrange(1, n+1):
for j in range(i, n+1, i):
result[j].append(i)
return result
MAX_N = 10**5
FACTORS = factors(MAX_N)
class Solution(object):
def minDifference(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[int]
"""
def backtracking(remain):
start = curr[-1] if curr else 1
if len(curr) == k-1 and remain >= start:
curr.append(remain)
if not result or result[-1]-result[0] > curr[-1]-curr[0]:
result[:] = curr
curr.pop()
return
factors = FACTORS[remain]
for i in xrange(bisect.bisect_left(factors, start), len(factors)):
curr.append(factors[i])
backtracking(remain//factors[i])
curr.pop()
result, curr = [], []
backtracking(n)
return result
# Time: O(k * (n^(1/2) * n^(1/4) * n^(1/8) * n^(1/6) + n^(1/2) * n^(1/4) * n^(1/8) + n^(1/2) * n^(1/4) + n^(1/2))) <= O(k^2 * n)
# Space: O(k)
# backtracking, number theory
class Solution2(object):
def minDifference(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[int]
"""
def factors(n):
for i in xrange(1, n+1):
if i*i > n:
break
if n%i:
continue
yield i
if n//i != i:
yield n//i
def backtracking(remain):
start = curr[-1] if curr else 1
if len(curr) == k-1 and remain >= start:
curr.append(remain)
if not result or result[-1]-result[0] > curr[-1]-curr[0]:
result[:] = curr
curr.pop()
return
for i in factors(remain):
if i < start:
continue
curr.append(i)
backtracking(remain//i)
curr.pop()
result, curr = [], []
backtracking(n)
return result
# Time: O(2^(k-1) * k * n)
# Space: O(k)
# backtracking, number theory
class Solution3(object):
def minDifference(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[int]
"""
def factors(n):
for i in xrange(1, n+1):
if i*i > n:
break
if n%i:
continue
yield i
if n//i != i:
yield n//i
def backtracking(remain):
if len(curr) == k-1:
curr.append(remain)
if not result or max(result)-min(result) > max(curr)-min(curr):
result[:] = curr
curr.pop()
return
for i in factors(remain):
curr.append(i)
backtracking(remain//i)
curr.pop()
result, curr = [], []
backtracking(n)
return result