- Identify the ordered answer range or sorted search domain.
- Write a predicate whose truth changes only once.
- Move the appropriate boundary after each midpoint check and return the final feasible position.
Code notes
- 80 lines of Python from the credited upstream file maximize-subarray-gcd-score.py.
- The implementation visibly relies on sequence storage.
- 2 loop blocks detected.
Complexity
Multiply the logarithmic number of midpoint checks by the cost of one predicate evaluation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 45class Solution(object):6 def maxGCDScore(self, nums, k):7 """8 :type nums: List[int]9 :type k: int10 :rtype: int11 """12 def gcd(a, b):13 while b:14 a, b = b, a%b15 return a16 17 lookup = [0]*len(nums)18 for i in xrange(len(nums)):19 while nums[i]&1 == 0:20 nums[i] >>= 121 lookup[i] += 122 lookup2 = [[] for _ in xrange(max(lookup)+1)]23 for i, e in enumerate(lookup):24 lookup2[e].append(i)25 result = 026 dp = {}27 for i, x in enumerate(nums):28 new_dp = {}29 new_dp[x, lookup[i]] = [i]*230 for (g, e), v in dp.iteritems(): 31 ng = gcd(g, x)32 ne = min(e, lookup[i])33 if (ng, ne) not in new_dp:34 new_dp[ng, ne] = [float("inf")]*235 new_dp[ng, ne][0] = min(new_dp[ng, ne][0], v[0])36 left = bisect_left(lookup2[ne], v[0]) 37 right = bisect_right(lookup2[ne], i)-1 38 new_dp[ng, ne][1] = min(new_dp[ng, ne][1], v[0] if right-left+1 <= k else lookup2[ne][right-k]+1)39 dp = new_dp40 for (g, e), v in dp.iteritems(): 41 result = max(result, g*(i-v[0]+1)<<e, g*(i-v[1]+1)<<(e+1))42 return result43 44 45464748class Solution2(object):49 def maxGCDScore(self, nums, k):50 """51 :type nums: List[int]52 :type k: int53 :rtype: int54 """55 def gcd(a, b):56 while b:57 a, b = b, a%b58 return a59 60 def lower_bit(x):61 return x&-x62 63 result = 064 for i in xrange(len(nums)):65 mn = float("inf")66 g = cnt = 067 for j in xrange(i, len(nums)):68 g = gcd(g, nums[j])69 bit = lower_bit(nums[j])70 if bit < mn:71 mn = bit72 cnt = 073 if bit == mn:74 cnt += 175 result = max(result, g*(j-i+1)*(2 if cnt <= k else 1))76 if g*(len(nums)-i)*2 <= result:77 break78 return result79 80