Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 了解这两种缩放特性之间的差异_Algorithm_Performance_Big O_Scaling - Fatal编程技术网

Algorithm 了解这两种缩放特性之间的差异

Algorithm 了解这两种缩放特性之间的差异,algorithm,performance,big-o,scaling,Algorithm,Performance,Big O,Scaling,我需要帮助理解一本关于算法的书中的以下段落- 自然组合问题的搜索空间趋于增长 以指数形式表示输入的大小N;如果输入大小增加 通过1,可能性的数量成倍增加。我们会 像一个好的算法,对于这样的问题要有更好的伸缩性 属性:当输入大小增加一个常数因子时,例如 因子2-算法应该只慢一些常数 因子C 我真的不明白为什么一个比另一个好。如果有人能提出任何例子来帮助我理解,那就非常感谢了。 让我们考虑下面的问题:你得到了一个数字列表,你想找到那个列表中最长的子序列,其中的数字是按顺序排列的。例如,给定序列 2

我需要帮助理解一本关于算法的书中的以下段落-

自然组合问题的搜索空间趋于增长 以指数形式表示输入的大小N;如果输入大小增加 通过1,可能性的数量成倍增加。我们会 像一个好的算法,对于这样的问题要有更好的伸缩性 属性:当输入大小增加一个常数因子时,例如 因子2-算法应该只慢一些常数 因子C


我真的不明白为什么一个比另一个好。如果有人能提出任何例子来帮助我理解,那就非常感谢了。

让我们考虑下面的问题:你得到了一个数字列表,你想找到那个列表中最长的子序列,其中的数字是按顺序排列的。例如,给定序列

2  7  1  8  3  9  4  5  0  6
您可以按如下方式形成子序列[2,7,8,9]:

2  7  1  8  3  9  4  5  0  6
^  ^     ^     ^
但这里还有一个更长的[1,3,4,5,6]可供选择:

2  7  1  8  3  9  4  5  0  6
      ^     ^     ^  ^     ^
我相信,这恰好是按递增顺序排列的最长子序列,不过如果我弄错了,请告诉我

现在我们有了这个问题,在一般情况下,如果你有一个n个数字的列表,我们将如何解决这个问题?让我们从一个不太好的选择开始。一种可能是列出原始数字列表的所有子序列,然后过滤掉所有不按递增顺序排列的数字,然后从我们找到的所有数字中选出最长的一个。例如,给出以下简短列表:

2  7  1  8
我们将形成所有可能的子序列,如下所示:

  • []
  • [8]
  • [1]
  • [1,8]
  • [7]
  • [7,8]
  • [7,1]
  • [7,1,8]
  • [2]
  • [2,8]
  • [2,1]
  • [2,1,8]
  • [2,7]
  • [2,7,8]
  • [2,7,1]
  • [2,7,1,8]
哎呀,那张单子挺长的。但是通过观察它,我们可以看到最长的递增子序列的长度为2,我们可以选择很多种

现在,当我们的输入列表越来越长时,它的伸缩性如何?这里有一些需要思考的事情-这个新列表有多少子序列,我通过在现有列表的末尾添加3来完成

2  7  1  8  3
每个现有的子序列在这里仍然是一个完全有效的子序列。但除此之外,我们还可以形成一系列新的子序列。事实上,我们可以取任何现有的子序列,然后在它的末尾加上一个3。这意味着,如果长度为4的列表有S子序列,那么长度为5的列表将有2S子序列

更一般地说,您可以看到,如果您获取一个列表并在其末尾再添加一个元素,那么可用子序列的数量将增加一倍。这是一个数学事实,它本身既不好也不坏,但如果我们列出所有这些子序列,并检查它们中的每一个,看看它们是否有一些属性,我们将遇到麻烦,因为这意味着将有大量子序列。我们已经看到四元素列表有16个子序列。这意味着五元素列表有32个子序列,六元素列表有64个子序列,更一般地说,n元素列表有2n个子序列

有了这样的洞察力,让我们快速计算一下。我们需要检查多少子序列,比如说,是否有一个300元素的列表?我们可能要检查2300个,这个数字比可观测宇宙中的原子数量还要大!哎呀。这需要比我们更多的时间

另一方面,有一个漂亮的算法叫做,它总是能找到最长的递增子序列,而且很容易找到。你可以通过玩一个小游戏来做到这一点。您将把列表中的每一项放在许多堆中的一堆中。要确定要拾取的桩,请查找顶部编号大于相关编号的第一个桩,并将其放置在顶部。如果用这种方法找不到一堆,请将数字放在最右边自己的一堆中

例如,给定此原始列表:

2  7  1  8  3  9  4  5  0  6
在玩完游戏后,我们将得到以下几堆:

0
1    3    4    5
2    7    8    9    6
这里有一个惊人的事实:使用的桩的数量等于最长的递增子序列的长度。此外,您可以通过以下方式找到子序列:每次在桩顶部放置数字时,记下桩左侧顶部的数字。如果我们用上面的数字来做这件事,我们会发现:;括号中的数字告诉我们,当我们放下数字时,左边堆栈的顶部是什么:

0
1     3 (1)    4 (3)    5 (4)
2     7 (2)    8 (7)    9 (8)    6 (5)
要找到我们想要的子序列,从最左边的堆的顶部开始。把这个数字写下来,然后在括号里找到这个数字,然后重复这个过程。在这里这样做会得到6,5,4,3,1,如果反转,它就是1,3,4,5,6,最长的递增子序列!(哇!)

所以现在的问题是这个过程有多快。把第一个数字放下来需要一个单位的工作——只需把它放在自己的堆里。将第二个数字放下来最多需要两个工作单元——我们必须查看第一堆的顶部,并有选择地将数字放在第二堆中。放置第三个数字最多需要三个工作单元-我们必须查看最多两堆,并可能将数字放置到其自己的第三堆中。更一般地说,放下第k个数字需要k个工作单位。总的来说,这意味着我们正在做的工作大致上是

1+2+3+…+n

如果我们有n个元素。这是一个著名的和,叫做高斯和,它简化为n2/2。所以我们可以说,我们需要做大约2/2单位的功来解决这个问题