📌  相关文章
📜  使所有数组元素等于 1 所需的成本(1)

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

使所有数组元素等于 1 所需的成本

当我们需要让一个数组中的所有元素都变成 1,我们通常会想到对每个元素进行遍历,然后将其值设为 1。但是这种方法的时间复杂度为 $O(n)$,需要遍历整个数组,当数组较大时性能会很低。

接下来我们将介绍两个更加高效的方法,分别是翻转法和位运算法。

翻转法

我们可以将翻转操作(将 0 变为 1 或将 1 变为 0)看作一种费用,每次翻转都需要付出这个费用。考虑到我们只需要将元素变成 1,我们可以将翻转 0 变为 1 的费用称为“1 的成本”,翻转 1 变为 1 的费用称为“0 的成本”。

假设我们现在需要将数组 $nums$ 中的所有元素变成 1,可以按照以下步骤进行:

  1. 初始化翻转次数 $count=0$ 和 0 的成本 $zeroCost=0$;
  2. 遍历数组 $nums$,对于每个元素 $num$,如果 $num=1$,则不做任何操作,否则分别计算翻转为 1 的成本和翻转为 0 的成本,选择成本较小者进行翻转,并将 $count$ 加上对应的成本;
  3. 返回 $count$。

下面是一种基于 Python 语言的实现:

def min_cost_to_make_all_ones(nums):
    count = 0
    zeroCost = 0

    for num in nums:
        if num == 1:
            continue

        oneCost = zeroCost + 1
        zeroCost += 1
        count += min(oneCost, zeroCost)

    return count

以上代码的时间复杂度为 $O(n)$,空间复杂度为 $O(1)$。

位运算法

我们知道,一个数的二进制形式中最低位的一定是 0 或 1,因此我们可以借助位运算来进行优化。假设我们现在需要将数组 $nums$ 中的所有元素变成 1,可以按照以下步骤进行:

  1. 初始化翻转次数 $count=0$ 和 0 的成本 $zeroCost=0$;
  2. 遍历数组 $nums$,对于每个元素 $num$,首先计算 $num$ 的二进制表示中 1 的数量 $oneCount$ 和 0 的数量 $zeroCount$。然后,计算将 $num$ 变为 1 的成本 $oneCost$ 和将 $num$ 变为 0 的成本 $zeroCost$,其中 $oneCost=zeroCount$,$zeroCost=oneCount$。选择成本较小者进行翻转,并将 $count$ 加上对应的成本;
  3. 返回 $count$。

下面是一种基于 Python 语言的实现:

def min_cost_to_make_all_ones(nums):
    count = 0
    zeroCost = 0

    for num in nums:
        oneCount = bin(num).count('1')
        zeroCount = len(bin(num))-oneCount-2
        oneCost = zeroCount
        zeroCost = oneCount
        count += min(oneCost, zeroCost)

    return count

以上代码的时间复杂度为 $O(n\log_2{m})$,其中 $m$ 是数组中的最大值。空间复杂度为 $O(1)$。