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

📅  最后修改于: 2023-12-03 14:53:58.645000             🧑  作者: Mango

左侧可被当前元素整除的元素数 | 2套

这是一个简单的算法问题,在给定整数数组中,对于每个元素,计算其左侧有多少个数可以被其整除,并将结果除以 2。

示例

给定数组 nums = [1, 2, 3, 4, 5, 6],那么应该返回 [0, 0, 1, 1, 2, 2]。

解释:

对于元素 1,左侧没有数字可以被整除,返回 0。
对于元素 2,左侧没有数字可以被整除,返回 0。
对于元素 3,左侧有 1 个数字 1 可以被整除,返回 1。
对于元素 4,左侧有 1 个数字 2 可以被整除,返回 1。
对于元素 5,左侧有 2 个数字 1 和 5 可以被整除,返回 2。
对于元素 6,左侧有 2 个数字 1 和 2 可以被整除,返回 2。
解法

这个问题可以使用暴力解法,对于数组中的每个元素,扫描其左侧的所有元素并计算可以被其整除的元素数目。这个算法的时间复杂度是 $O(n^2)$,其中 $n$ 是数组中元素的数目。

def count_divisible_numbers(nums):
    n = len(nums)
    ans = [0] * n
    for i in range(1, n):
        cnt = 0
        for j in range(i):
            if nums[i] % nums[j] == 0:
                cnt += 1
        ans[i] = cnt // 2
    return ans

这个算法不是非常高效,无法通过在大数组上运行,因此我们需要一个更快的算法。

一个更好的解法是使用动态规划。对于数组中的每个元素,它可以由所有可以被其整除的元素转移而来。因此,我们可以为每个元素保存一个集合,表示所有可以转移到该元素的元素的下标。

def count_divisible_numbers(nums):
    n = len(nums)
    graph = [set() for _ in range(n)]
    for i in range(n):
        for j in range(i):
            if nums[i] % nums[j] == 0:
                graph[i].add(j)

    ans = [0] * n
    for i in range(n - 1, -1, -1):
        for j in graph[i]:
            ans[j] += ans[i] + 1
        ans[i] = ans[i] // 2

    return ans

这个算法的时间复杂度是 $O(n^2)$,空间复杂度是 $O(n^2)$,其中 $n$ 是数组中元素的数目。

总结

以上介绍了两种算法来解决左侧可被当前元素整除的元素数 | 2套问题。第一种算法是暴力扫描,时间复杂度是 $O(n^2)$。第二种算法使用动态规划,时间复杂度也是 $O(n^2)$,但相对于暴力扫描,具有更好的空间效率。