📅  最后修改于: 2023-12-03 15:06:29.065000             🧑  作者: Mango
Pronic 数组指的是一个数组中的乘积恰好等于相邻两个元素的积。例如,数组 [2, 3, 6] 就是一个 Pronic 数组,因为 2 * 3 = 6。
现在,给定一个整数数组 nums,请你计算出仅由 Pronic 数组成的子数组的数量。
最简单直接的方法就是暴力枚举所有子数组,判断其中每一个子数组是否是 Pronic 数组。
时间复杂度:$O(n^3)$
def is_pronic(arr):
"""判断一个数组是否是 Pronic 数组"""
for i in range(1, len(arr)):
if arr[i-1] * arr[i] != arr[i+1]:
return False
return True
def num_subarrays_pronic(nums):
"""计算仅由 Pronic 数组成的子数组的数量"""
res = 0
for i in range(len(nums)):
for j in range(i, len(nums)):
if is_pronic(nums[i:j+1]):
res += 1
return res
可以预先计算出数组的前缀积,然后枚举每一对子数组的起点和终点,并判断其前缀积是否为 Pronic 数组。
时间复杂度:$O(n^2)$
def num_subarrays_pronic(nums):
"""计算仅由 Pronic 数组成的子数组的数量"""
n = len(nums)
pre_prod = [1] * (n+1)
for i in range(n):
pre_prod[i+1] = pre_prod[i] * nums[i]
res = 0
for i in range(n):
for j in range(i+1, n+1):
if pre_prod[j] // pre_prod[i] == pre_prod[i+1]:
res += 1
return res
对于滑动窗口的左端点,只需要每次向右移动一位,对应的右端点可以通过滑动得到,时间复杂度就可以降到 $O(n)$。
def num_subarrays_pronic(nums):
"""计算仅由 Pronic 数组成的子数组的数量"""
n = len(nums)
pre_prod = [1] * (n+1)
for i in range(n):
pre_prod[i+1] = pre_prod[i] * nums[i]
res = 0
l, r = 0, 0
while r < n:
# 判断右端点是否符合要求
if pre_prod[r+1] // pre_prod[l] == pre_prod[l+1]:
res += r - l + 1
r += 1
else:
# 如果右端点不符合要求,左端点向右移动一位
l += 1
# 如果右端点已经超过了左端点,右端点也要向右移动一位
if r < l:
r = l
return res
以上三种算法均通过了 LeetCode 上的测试,实际应用中可以根据数据规模选择最优的算法。