class Solution {
public:
int findValidSplit(vector<int>& nums) {
}
};
6309. 分割数组使乘积互质
给你一个长度为 n
的整数数组 nums
,下标从 0 开始。
如果在下标 i
处 分割 数组,其中 0 <= i <= n - 2
,使前 i + 1
个元素的乘积和剩余元素的乘积互质,则认为该分割 有效 。
nums = [2, 3, 3]
,那么在下标 i = 0
处的分割有效,因为 2
和 9
互质,而在下标 i = 1
处的分割无效,因为 6
和 3
不互质。在下标 i = 2
处的分割也无效,因为 i == n - 1
。返回可以有效分割数组的最小下标 i
,如果不存在有效分割,则返回 -1
。
当且仅当 gcd(val1, val2) == 1
成立时,val1
和 val2
这两个值才是互质的,其中 gcd(val1, val2)
表示 val1
和 val2
的最大公约数。
示例 1:
输入:nums = [4,7,8,15,3,5] 输出:2 解释:上表展示了每个下标 i 处的前 i + 1 个元素的乘积、剩余元素的乘积和它们的最大公约数的值。 唯一一个有效分割位于下标 2 。
示例 2:
输入:nums = [4,7,15,8,3,5] 输出:-1 解释:上表展示了每个下标 i 处的前 i + 1 个元素的乘积、剩余元素的乘积和它们的最大公约数的值。 不存在有效分割。
提示:
n == nums.length
1 <= n <= 104
1 <= nums[i] <= 106
原站题解
java 解法, 执行用时: 98 ms, 内存消耗: 42.2 MB, 提交时间: 2023-03-09 14:31:37
class Solution { public int findValidSplit(int[] nums) { int n = nums.length; var left = new HashMap<Integer, Integer>(); // left[p] 表示质数 p 首次出现的下标 var right = new int[n]; // right[i] 表示左端点为 i 的区间的右端点的最大值 for (int i = 0; i < n; i++) { int x = nums[i]; for (int d = 2; d * d <= x; ++d) // 分解质因数 if (x % d == 0) { if (left.containsKey(d)) right[left.get(d)] = i; // 记录左端点对应的右端点的最大值 else left.put(d, i); // 第一次遇到质数 d for (x /= d; x % d == 0; x /= d) ; } if (x > 1) if (left.containsKey(x)) right[left.get(x)] = i; else left.put(x, i); } for (int l = 0, maxR = 0; l < n; l++) { if (l > maxR) // 最远可以遇到 maxR return maxR; // 也可以写 l-1 maxR = Math.max(maxR, right[l]); } return -1; } }
golang 解法, 执行用时: 164 ms, 内存消耗: 6.4 MB, 提交时间: 2023-03-09 14:31:07
func findValidSplit(nums []int) int { left := map[int]int{} // left[p] 表示质数 p 首次出现的下标 right := make([]int, len(nums)) // right[i] 表示左端点为 i 的区间的右端点的最大值 f := func(p, i int) { if l, ok := left[p]; ok { right[l] = i // 记录左端点 l 对应的右端点的最大值 } else { left[p] = i // 第一次遇到质数 p } } for i, x := range nums { for d := 2; d*d <= x; d++ { // 分解质因数 if x%d == 0 { f(d, i) for x /= d; x%d == 0; x /= d { } } } if x > 1 { f(x, i) } } maxR := 0 for l, r := range right { if l > maxR { // 最远可以遇到 maxR return maxR // 也可以写 l-1 } maxR = max(maxR, r) } return -1 } func max(a, b int) int { if a < b { return b }; return a }
python3 解法, 执行用时: 4196 ms, 内存消耗: 16.7 MB, 提交时间: 2023-03-09 14:30:21
''' 质因子p, ''' class Solution: def findValidSplit(self, nums: List[int]) -> int: left = {} # left[p] 表示质数 p 首次出现的下标 right = [0] * len(nums) # right[i] 表示左端点为 i 的区间的右端点的最大值 def f(p: int, i: int) -> None: if p in left: right[left[p]] = i # 记录左端点 l 对应的右端点的最大值 else: left[p] = i # 第一次遇到质数 p for i, x in enumerate(nums): d = 2 while d * d <= x: # 分解质因数 if x % d == 0: f(d, i) x //= d while x % d == 0: x //= d d += 1 if x > 1: f(x, i) max_r = 0 for l, r in enumerate(right): if l > max_r: # 最远可以遇到 max_r return max_r # 也可以写 l-1 max_r = max(max_r, r) return -1