【问题标题】:Finding first even number in a list with algorithm complexity better than linear在算法复杂度优于线性的列表中找到第一个偶数
【发布时间】:2020-01-28 22:00:42
【问题描述】:

我的列表首先是奇数元素,然后是偶数元素,所以奇数元素首先出现在列表中,然后是偶数元素。例如:

list = [5,99,3,7,111,13,4,24,4,8]

所以偶数元素在编号为 4 的奇数元素之后开始。以线性复杂度执行此操作会很简单,但它必须具有更好的复杂性,因此我想到了二进制搜索,但我不知道如何在这种情况下实现它。感谢帮助。

【问题讨论】:

  • 使用二分搜索来确定它从哪个索引开始交换。您可以将偶数元素视为“太大”,将奇数元素视为“太小”。
  • 如果问题仍然适用于 C++,那么 std::partition_point 可以完成这项工作。 (有类似的例子)。
  • @ManojBanik 二进制搜索是 O(log n)
  • @Mitchel Paulin,我的错,我本来打算写 O(log n),谢谢指正。

标签: python algorithm list complexity-theory


【解决方案1】:

由于值已经组织好,只需取集合(数组、列表)的中间部分并检查它是偶数还是奇数。

是吗?然后第一个偶数值位于集合的前半部分,您可以丢弃后半部分,或者它是当前的。

很奇怪吗?然后第一个偶数值还没有出现,丢弃前半部分,将第二个作为新的集合并继续这样做,直到找到它为止。

一些视觉指南: https://www.freecodecamp.org/news/binary-search-in-python-visual-introduction/

【讨论】:

    【解决方案2】:

    我们知道二分查找何时起作用的标准。由于数组具有 000..0111..1 属性,我们可以在这里轻松地使用二分查找。

    在二分搜索中有两个边界,可以说它们是低和高,其中低 = 数组的第一个索引,高 = 数组的最后一个索引。在每个迭代器中,我们使用 (low + high) / 2 从低到高找到 midium 元素。所以当我们找到要检查的 midium 元素时,我们可以在这里做什么?我们可以检查它是否是偶数。如果数字是奇数,我们可以忽略从低到中索引的元素,因为从低到中索引的所有元素都是奇数。在这种情况下,我们可以将我们的下边界低更改为中 + 1。现在如果中索引是偶数,那么中索引可以是我们的答案,但答案也可以在低到中 - 1 索引之间。所以我们将把我们的上边界减少到 midium - 1。

    因此我们可以得到偶数的最小索引。

    代码:

    ans = len(list)
    low = 0, high = len(list) - 1
    while low <= high:
        mid = (low + high) // 2
        if list[mid] % 2:
            low = mid + 1
        else:
            ans = mid
            high = mid - 1
    
    # here ans is the index of the first even number
    

    【讨论】:

      【解决方案3】:

      Python 的bisect module 带有非常简单但经过良好测试的source code

      尝试通过将 a[mid] &lt; x 测试替换为偶数/奇数测试 a[mid] % 2 == 1 来修改该代码。

      这应该可以帮助您解决问题,但无需我们实际为您编写代码。

      祝你好运:-)

      【讨论】:

        【解决方案4】:

        Rayner Fernandez 在另一个答案中得到了正确的答案:二分搜索在 O(log n) 时间内完成了这项工作。这样做的原因是输入列表有效地按 parity 的降序排序。因为你只关心奇偶校验,这对于二分搜索已经足够了;就二进制搜索而言,您的输入相当于一个全 0 和 1 的输入。您可以将其视为运行二进制搜索查找 1/2,并返回在找不到目标之前查看的最后一个索引二进制搜索。

        总结:检查列表中间的值。如果是偶数,你知道最后一个奇数元素在左边;否则,如果它是奇数,则您知道最后一个奇数元素是该元素或其右侧。然后,在您确定存在最后一个奇数元素的最小子数组上重复相同的过程。

        【讨论】:

          猜你喜欢
          • 2016-01-16
          • 1970-01-01
          • 2013-03-07
          • 1970-01-01
          • 2015-04-24
          • 2017-03-04
          • 1970-01-01
          • 2021-01-20
          • 2020-03-05
          相关资源
          最近更新 更多