-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathmaximize-subarray-gcd-score.py
More file actions
79 lines (72 loc) · 2.41 KB
/
maximize-subarray-gcd-score.py
File metadata and controls
79 lines (72 loc) · 2.41 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
# Time: O(nlogn * logr), r = max(nums)
# Space: O(n + logr)
# number theory, suffix-gcd states, dp, binary search
class Solution(object):
def maxGCDScore(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
def gcd(a, b):
while b:
a, b = b, a%b
return a
lookup = [0]*len(nums)
for i in xrange(len(nums)):
while nums[i]&1 == 0:
nums[i] >>= 1
lookup[i] += 1
lookup2 = [[] for _ in xrange(max(lookup)+1)]
for i, e in enumerate(lookup):
lookup2[e].append(i)
result = 0
dp = {}
for i, x in enumerate(nums):
new_dp = {}
new_dp[x, lookup[i]] = [i]*2
for (g, e), v in dp.iteritems(): # |g * e| = O(logr)
ng = gcd(g, x)
ne = min(e, lookup[i])
if (ng, ne) not in new_dp:
new_dp[ng, ne] = [float("inf")]*2
new_dp[ng, ne][0] = min(new_dp[ng, ne][0], v[0])
left = bisect_left(lookup2[ne], v[0]) # Time: O(logn)
right = bisect_right(lookup2[ne], i)-1 # Time: O(logn)
new_dp[ng, ne][1] = min(new_dp[ng, ne][1], v[0] if right-left+1 <= k else lookup2[ne][right-k]+1)
dp = new_dp
for (g, e), v in dp.iteritems(): # |g * e| = O(logr)
result = max(result, g*(i-v[0]+1)<<e, g*(i-v[1]+1)<<(e+1))
return result
# Time: O(n^2 + n * logr), r = max(nums)
# Space: O(1)
# number theory, brute force
class Solution2(object):
def maxGCDScore(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
def gcd(a, b):
while b:
a, b = b, a%b
return a
def lower_bit(x):
return x&-x
result = 0
for i in xrange(len(nums)):
mn = float("inf")
g = cnt = 0
for j in xrange(i, len(nums)):
g = gcd(g, nums[j])
bit = lower_bit(nums[j])
if bit < mn:
mn = bit
cnt = 0
if bit == mn:
cnt += 1
result = max(result, g*(j-i+1)*(2 if cnt <= k else 1))
if g*(len(nums)-i)*2 <= result:
break
return result