📌  相关文章
📜  可以被当前元素整除的左侧元素的计数(1)

📅  最后修改于: 2023-12-03 15:07:26.810000             🧑  作者: Mango

介绍

这是一个计算一个数组中,每个元素左侧有多少个元素可以被它整除的算法。该算法分别使用了暴力求解和前缀积优化的解法。可以运用到解决数学问题、动态规划等场景。

示例

输入: nums = [1, 2, 3, 4, 5]

输出: [0, 1, 1, 2, 1]

解释:

元素1左侧没有元素,故0。

元素2左侧有元素1可以整除,故1。

元素3左侧有元素1可以整除,故1。

元素4左侧有元素1和2可以整除,故2。

元素5左侧有元素1可以整除,故1。

算法解析
暴力求解

暴力求解的思路很简单,对于每个元素,枚举它左侧的所有元素,计算可以被当前元素整除的元素数量。时间复杂度是$O(n^2)$。

def solution1(nums):
    n = len(nums)
    ans = []
    for i in range(n):
        cnt = 0
        for j in range(i):
            if nums[i] % nums[j] == 0:
                cnt += 1
        ans.append(cnt)
    return ans
前缀积优化

观察暴力解法的过程,可以发现对于每次计算,我们都需要循环当前元素左侧的所有元素,这是一个重复的过程。那么能不能把所有已处理的元素信息保存下来,用O(1)的时间复杂度来快速查找呢?答案是可以。我们可以使用前缀积,将所有已处理的元素的信息乘起来,存储在一个新数组中。这样在计算时,只需要查找当前元素左侧已处理元素的信息,再乘上这个新数组中的值即可。时间复杂度是$O(n)$。

def solution2(nums):
    n = len(nums)
    ans = [0] * n
    prefix_product = [1] * n
    for i in range(1, n):
        prefix_product[i] = prefix_product[i-1] * nums[i-1]
    for i in range(n):
        ans[i] = prefix_product[i:].count(0)
    return ans
总结

通过前缀积优化,我们得到了一个时间复杂度是$O(n)$的算法,比暴力解法快了很多。但实际应用中,如果不是数据量很大,使用暴力解法是没有问题的。同时,算法的实现可以通过使用字典等数据结构进一步优化,让计算速度更快。