LC 2584. 分割数组使乘积互质
https://leetcode.cn/contest/weekly-contest-335/problems/split-the-array-to-make-coprime-products/
这题最粗俗的解法就是分解因子,然后记录每个位置上可能的因子个数,然后不断往前推,使得某个点上所有因子的个数都涵盖到了。
我看了这个解法觉得特别有意思 https://leetcode.cn/problems/split-the-array-to-make-coprime-products/solution/ben-zhi-shi-tiao-yue-you-xi-by-endlessch-8chd/
大致思想是,记录每个位置上这个数,它所有的可能因子最远距离。一旦我选择了这个数,那么我就需要选择这个因子,那么就必须跳跃到这个因子的最远位置。
这里面数据结构也非常有意义:
- left[p] 表示p因子第一次出现的位置
- right[i] 表示位置i包含因子的最远位置
from typing import List
def get_primes(M):
P = [0] * (M + 1)
for i in range(2, M + 1):
if P[i] == 1: continue
for j in range(2, M + 1):
if i * j > M: break
P[i * j] = 1
primes = []
for i in range(2, M + 1):
if P[i] == 0:
primes.append(i)
return primes
class Solution:
def findValidSplit(self, nums: List[int]) -> int:
M = min(max(nums), 10 ** 3)
primes = get_primes(M)
left = {}
right = [0] * (len(nums))
def update(p, idx):
if p not in left:
pos = idx
left[p] = idx
else:
pos = left[p]
right[pos] = idx
for idx, x in enumerate(nums):
for p in primes:
if x % p == 0:
while x % p == 0:
x = x // p
update(p, idx)
if x > 1:
update(x, idx)
ans = 0 # 假设当前最远位置
for idx, r in enumerate(right):
if idx > ans:
return ans
ans = max(ans, r)
return -1