【问题标题】:Big-Oh notation for a single while loop covering two halves of an array with two iterator vars单个 while 循环的 Big-Oh 表示法,覆盖具有两个迭代器变量的数组的两半
【发布时间】:2015-09-07 05:59:18
【问题描述】:

试图复习我对 Big-O 的理解以进行测试(显然需要非常基本的 Big-O 理解)我已经提出并在我的书中做一些练习题。

他们给了我以下sn-p

public static void swap(int[] a)
{
    int i = 0;
    int j = a.length-1;

    while (i < j)
    {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
        i++;
        j--;
    }
}

我觉得很容易理解。它有两个迭代器,每个迭代器都覆盖了数组的一半,工作量固定(我认为它们的时钟都在 O(n/2))

因此 O(n/2) + O(n/2) = O(2n/2) = O(n)

现在请原谅,因为这是我目前的理解,也是我尝试解决问题的方法。我在网上找到了很多 big-o 的示例,但没有一个与迭代器基本同时递增和修改数组的情况非常相似。

它有一个循环的事实让我觉得它无论如何都是 O(n)。

有人介意帮我解决这个问题吗?

谢谢

【问题讨论】:

  • 仅供参考:即使你只迭代了半个数组——例如sumOddIndexElements()——它仍然是 O(n)。 1/2 的常数因子消失了。当您开始分析更复杂的算法时,在分析早期从精确计数切换到大 O 会很有帮助。然后您的中间步骤变得更简单,因为您可以丢弃术语。 IE。如果一个子程序完成 O(n) + O(log n) 的工作,您可以立即将其减少到 O(n) 以进行其余的分析。
  • @japreiss 对不起,我不想以任何方式冗余,但你的最后一句话让我有点困惑。如果我理解正确的话,O(log n) 在某个点上对于 O(n) 来说将变得微不足道,以至于不值得计算时间效率,因此我们放弃它?
  • 根据大 O 的定义,当您添加项时,您始终可以删除除渐近最大的项之外的所有项。你可以证明n + log n &lt; 2n2n 是 O(n)。所以是的,它是微不足道的,以非常明确的方式。

标签: java algorithm big-o


【解决方案1】:

它有一个循环的事实让我觉得它无论如何都是 O(n)。

这是正确的。不是因为它是一个循环,而是因为它是一个循环,它依赖于数组大小的一个常数因子:big-O 表示法忽略了任何常数因子。 O(n) 表示对算法的唯一影响是基于数组的大小。它实际上需要一半的时间,对于 big-O 来说并不重要。

换句话说:如果你的算法需要时间n+XXnXn + Y 都将归结为 big-O O(n)

如果循环的大小被改变而不是一个常数因子,它会变得不同,但是作为n的对数或指数函数,例如如果大小是100并且循环是2,大小是@ 987654329@,循环为3,大小为10000,循环为4。在这种情况下,例如,O(log(n))

如果循环与大小无关,也会有所不同。即,如果您总是循环 100 次,无论循环大小如何,您的算法将是 O(1)(即,在某个恒定时间内运行)。

我还想知道我想出的等式是否正确。

是的。事实上,如果你的等式最终是某种形式的n * C + Y,其中C 是某个常数,Y 是某个其他值,那么无论see 是否大于1,结果都是O(n),或小于1

【讨论】:

  • 感谢您的回复。我还想知道我想出的等式是否在正确的范围内。像这样从数学上考虑它会有所帮助,但我正在用它在黑暗中拍摄。在该特定方面进行一些验证会很棒。我假设它是O(n/2) + O(n/2) or just O(n/2) and then I ignore the /2 alltogether
【解决方案2】:

关于循环,你是对的。循环将确定大 O。但循环仅对数组的一半运行。

所以它。 2 + 6 *(n/2)

如果我们使 n 非常大,其他数字真的很小。所以他们不重要。 所以它的 O(n)。

假设您正在运行 2 个单独的循环。 2 + 6* (n/2) + 6*(n/2) 。在这种情况下,它将再次成为 O(n)。

但是如果我们运行一个嵌套循环。 2+ 6*(n*n)。那么它将是 O(n^2)

始终删除常量并进行数学运算。你明白了。

【讨论】:

  • 所以让我快速分解一下。是 2 次初始操作 + 每次迭代的 6 次操作乘以总迭代次数?
  • 您使用O(2n) 的示例仍以O(n) 结尾,因为它仍然单独取决于大小。否则,如果两个循环产生不同的结果,那么半个循环也应该在大 O 表示法中产生不同的结果。
  • 对,我的错。 2 又是一个常数。那没关系。如果数量很大。
  • 嗯,2+6(n/2) 真的有那么大的估计吗?我认为线性中断是瓶颈,因此算法 O(n/2),取决于跳转/分叉的数量。对于 O 来说,这无关紧要,但通常是用于估计。
  • 常量 6 并不合适,因为您不知道各个操作的执行时间,这取决于机器。您可以根据变量分配的数量进行推理,每次迭代无疑是 5 个(i++i+= 1 的缩写)。
【解决方案3】:

随着j-i 在每次迭代中减少2 个单位,其中N/2 被采用(假设N=length(a))。

因此运行时间确实是O(N/2)。而O(N/2) 严格等价于O(N)

【讨论】:

    猜你喜欢
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 2020-05-26
    相关资源
    最近更新 更多