Questions tagged «algorithms»

算法是定义明确的问题解决方案的一系列明确定义的步骤。如果您的问题与算法的设计和分析有关,请使用此标签。

11
为什么实践中quicksort比其他排序算法更好?
在标准的算法当然我们被教导快速排序是平均和ø (Ñ 2)在最坏的情况下。同时,还研究了其他排序算法,它们在最坏的情况下为O (n log n )(例如mergesort和heapsort),在最坏的情况下甚至是线性时间(例如bubbleort),但还有一些额外的内存需求。Ø (ñ 日志n )O(nlog⁡n)O(n \log n)Ø (ñ2)O(n2)O(n^2)Ø (ñ 日志n )O(nlog⁡n)O(n \log n) 快速浏览一下更多的运行时间后,自然可以说quicksort 应该不如其他高效。 另外,考虑到学生在基础编程课程中学习到,递归通常并不太好,因为它会占用过多的内存,等等。因此(尽管这不是一个真正的论点),但这样的想法是快速排序可能不是真的很好,因为它是一种递归算法。 那么,为什么在实践中快速排序优于其他排序算法?它与真实数据的结构有关吗?它与计算机中内存的工作方式有关吗?我知道有些记忆要比其他记忆快,但是我不知道这是否是这种违反直觉的表现的真正原因(与理论估计相比)。 更新1:一个规范的答案是说,平均情况的所涉及的常数小于其他O (n log n )算法所涉及的常数。但是,我还没有看到用正确的计算代替仅凭直觉的想法的适当理由。Ø (ñ 日志n )O(nlog⁡n)O(n\log n)Ø (ñ 日志n )O(nlog⁡n)O(n\log n) 无论如何,正如某些答案所暗示的那样,似乎真正的区别发生在内存级别,在这种级别上,实现利用了计算机的内部结构,例如使用高速缓存比RAM快。讨论已经是有趣的,但我还是喜欢看关于内存管理更详细,因为它似乎是在回答有什么关系。 更新2:有几个网页提供了排序算法的比较,其中有些比其他网页更出色(最著名的是sorting-algorithms.com)。除了提供不错的视觉辅助外,这种方法也无法回答我的问题。

3
算法分析的魔力背后是否有一个系统?
关于如何分析算法的运行时间存在很多问题(例如,参见运行时分析和算法分析)。许多都是类似的,例如那些要求对嵌套循环或分而治之算法进行成本分析的方法,但是大多数答案似乎都是量身定制的。 另一方面,另一个通用问题的答案通过一些示例解释了更大的图景(尤其是关于渐近分析),但没有说明如何弄脏您的手。 有没有一种结构化的,通用的方法来分析算法的成本?成本可能是运行时间(时间复杂度),也可能是某种其他成本度量,例如执行的比较次数,空间复杂度或其他。 这应该成为一个参考问题,可以用来指导初学者。因此其范围比平常大。请小心给出一般的,有说服力的答案,至少由一个示例说明了这一点,但仍然涵盖了许多情况。谢谢!

14
为什么我可以看一下图并立即找到与另一点最接近的点,但是我花了O(n)时间来编程?
让我澄清一下: 给定一个散点图,该散点图具有给定数量的点n,如果我想在思维上找到最接近点的任何点,我可以立即忽略图中的大多数点,将选择范围缩小到附近的一些小而恒定的点。 但是,在编程中,给定一组点n,以便找到与任何一个点最接近的点,它需要检查每隔一点,即时间。O(n )O(n){\cal O}(n) 我猜测图形的视觉效果可能相当于我无法理解的某些数据结构;因为通过编程,通过将点转换为更结构化的方法(例如四叉树),可以在时间中找到中与个点最接近的点,或者将时间。Ñ ķ ⋅ 日志(Ñ )ø(登录Ñ )ķkkñnnk · 对数(n )k⋅log⁡(n)k\cdot\log(n)O(对数n )O(log⁡n){\cal O}(\log n) 但是,仍然没有已知的摊分算法(我可以找到)用于数据重组后的测点。O(1 )O(1){\cal O}(1) 那么,为什么仅凭视觉检查就可以做到这一点?

4
如何将有限自动机转换为正则表达式?
使用标准算法(例如汤普森算法),可以很容易地将正则表达式转换为接受相同语言的(最小)NFA 。但是,另一个方向似乎更乏味,有时结果表达式是混乱的。 有什么算法可以将NFA转换为等效的正则表达式?时间复杂度或结果大小是否有优势? 这应该是一个参考问题。请包括您的方法的一般说明以及不重要​​的示例。

13
如何愚弄“尝试一些测试用例”启发式算法:看起来正确但实际上不正确的算法
为了尝试测试某个问题的算法是否正确,通常的出发点是尝试在多个简单的测试案例上手动运行该算法-在一些示例问题实例(包括一些简单的“拐角案例”)上进行尝试”。这是一种很好的启发式方法:这是一种快速清除算法中许多错误尝试并了解为什么该算法无效的好方法。 但是,在学习算法时,有些学生很想停在这里:如果他们的算法在一些示例上都能正常工作,包括他们认为可以尝试的所有极端情况,那么他们得出的结论是算法必须正确。总是有一个学生问:“如果我可以在几个测试用例上尝试一下,为什么我需要证明我的算法正确?” 那么,如何欺骗“尝试一堆测试用例”启发式方法?我正在寻找一些很好的例子来表明这种启发式方法是不够的。换句话说,我正在寻找一个或多个算法的示例,这些示例从表面上看可能是正确的,并且在任何人都可能想出的所有小输入上输出正确答案,但是该算法实际上在哪里不起作用。也许该算法恰好在所有小输入上都能正常工作,仅对大输入失败,或者仅对具有异常模式的输入失败。 具体来说,我在寻找: 一种算法。该缺陷必须在算法级别上。我不是在寻找实现错误。(例如,该示例至少应与语言无关,并且该缺陷应与算法问题有关,而不是与软件工程或实现问题有关。) 有人可能会提出的一种算法。伪代码应该看起来至少看起来是正确的(例如,混淆或明显可疑的代码不是一个好例子)。如果这是某些学生在尝试解决作业或考试问题时真正想到的一种算法,则可加分。 通过概率较高的合理手动测试策略的算法。手动尝试一些小型测试用例的人应该不太可能发现该缺陷。例如,“手动模拟十二个小型测试用例的QuickCheck”应该不太可能揭示该算法不正确。 优选地,确定性算法。我已经看到许多学生认为“手动尝试一些测试用例”是检查确定性算法是否正确的合理方法,但是我怀疑大多数学生不会认为尝试几个测试用例是验证概率的好方法算法。对于概率算法,通常没有办法判断任何特定输出是否正确。而且您手头不足以对输出分布进行任何有用的统计检验。因此,我宁愿专注于确定性算法,因为它们更清楚地了解了学生的误解。 我想教导证明算法正确的重要性,并且希望使用一些这样的示例来帮助激发正确性的证明。我希望那些相对简单并且可以被大学生使用的例子;需要重型机械或大量数学/算法背景的示例不太有用。另外,我也不想使用“非自然”的算法;虽然构造一些怪异的人工算法来欺骗启发式方法可能很容易,但是如果看起来很不自然,或者构造了明显的后门只是为了欺骗这种启发式方法,那么它可能不会使学生信服。有什么好的例子吗?


5
学习用于同一目的的不同算法/数据结构的原因是什么?
自从我是一名本科生以来,我一直在想这个问题。这是一个普遍的问题,但我将在下面详细说明。 我见过很多算法-例如,对于最大流量问题,我知道大约3种算法可以解决该问题:福特-富克森(Ford-Fulkerson),埃德蒙兹-卡普(Edmonds-Karp)和狄尼克斯(Dinic),其中狄尼克斯具有最高的复杂性。 对于数据结构(例如堆),有二进制堆,二项式堆和Fibonacci堆,其中Fibonacci堆具有最佳的整体复杂性。 让我感到困惑的是:我们有什么理由需要全部了解它们吗?为什么不学习并熟悉最好的复杂性呢? 我知道这是最好的,如果我们都了解它们,我只是想知道是否有任何“更有效的”原因,例如某些问题/算法只能通过使用A而不是B来解决,等等。


2
快速排序分区:Hoare与Lomuto
Cormen中提到了两种快速排序分区方法: Hoare-Partition(A, p, r) x = A[p] i = p - 1 j = r + 1 while true repeat j = j - 1 until A[j] <= x repeat i = i + 1 until A[i] >= x if i < j swap( A[i], A[j] ) else return j …

8
图形搜索:广度优先与深度优先
搜索图时,有两种简单的算法:广度优先和深度优先(通常通过将所有邻接图节点添加到队列(广度优先)或堆栈(深度优先)来完成)。 现在,一个相对于另一个有什么优势吗? 我能想到的: 如果您希望数据在图表内很远,那么深度优先可能会更早找到它,因为您可以非常快速地进入图表的较深部分。 相反,如果您希望数据在图表中靠前很远,那么广度优先的结果可能会更早。 我有什么想念的吗?还是主要取决于个人喜好?

6
我们如何假设对数字的基本运算需要固定的时间?
通常,在算法中,我们不关心数字的比较,加法或减法-我们假设它们在时间。例如,当我们说基于比较的排序是时,我们就假设了这一点,但是当数字太大而无法放入寄存器时,我们通常将它们表示为数组,因此基本操作需要为每个元素进行额外的计算。O (n log n )O (1 )O(1)O(1)Ø (ñ 日志n )O(nlog⁡n)O(n\log n) 是否有证据表明可以在完成两个数字(或其他原始算术函数)的比较?如果不是,为什么我们说基于比较的排序是?O (n log n )O (1 )O(1)O(1)Ø (ñ 日志n )O(nlog⁡n)O(n\log n) 我遇到这个问题时,我回答了一个SO问题,我意识到,我的算法是不,因为我迟早要处理大INT,也是它不是伪多项式算法,它是。PO (n )O(n)O(n)PPP

4
MapReduce的新颖之处是什么?
几年前,MapReduce被誉为分布式编程的革命。也有批评家但总的来说是热心的炒作。它甚至获得了专利![1] 这个名字让人联想到的map和reduce函数式编程,但是当我阅读(维基百科) 映射步骤:主节点获取输入,将其分为较小的子问题,然后将其分配给工作节点。辅助节点可以依次再次执行此操作,从而导致多层树结构。工作节点处理较小的问题,并将答案传递回其主节点。 减少步骤:主节点然后收集所有子问题的答案,并以某种方式将它们组合起来以形成输出-最初试图解决的问题的答案。 或[2] MAP的内部原理: MAP将输入值分割为多个单词。MAP旨在将输入的每个给定键/值对与潜在的许多中间键/值对相关联。 REDUCE的内部要素: [REDUCE]执行命令式聚合(例如,减少):采用许多值,并将其减少为单个值。 我忍不住想:这是分而治之(在Mergesort的意义上),简单明了!那么,MapReduce中是否存在(概念上的)新颖性,还是只是在某些情况下有用的旧思想的新实现? 美国专利7,650,331:“有效进行大规模数据处理的系统和方法”(2010) Google的MapReduce编程模型 -R.Lämmel(2007)重新审视

3
用于交织数组的就地算法
给你一个元素的数组2 n2ñ2n 一种1个,一2,... ,一ñ,b1个,b2,… bñ一种1个,一种2,…,一种ñ,b1个,b2,…bña_1, a_2, \dots, a_n, b_1, b_2, \dots b_n 任务是使用就地算法对数组进行交织,以使生成的数组看起来像 b1个,一1个,b2,一2,… ,bñ,一ñb1个,一种1个,b2,一种2,…,bñ,一种ñb_1, a_1, b_2, a_2, \dots , b_n, a_n 如果就地需求不存在,我们可以轻松地创建一个新数组并复制给出O(n )的元素O(n)Ø(ñ)\mathcal{O}(n)时间算法的。 根据就地需求,分而治之算法将算法提高为θ (Ñ 登录n )θ(ñ日志⁡ñ)\theta(n \log n)。 所以问题是: 是否有一个时间算法,它也就位?O(n)Ø(ñ)\mathcal{O}(n) (注意:您可以假设使用统一成本的WORD RAM模型,因此就地转换为空间限制)。O(1)Ø(1个)\mathcal{O}(1)

9
随着问题的增加,是否有任何变得容易的问题?
这可能是一个荒谬的问题,但是随着输入量的增加,是否有可能实际上变得更容易解决的问题?我怀疑是否存在任何实际问题,但是也许我们可以发明具有这种性质的退化问题。例如,当它变大时,它可能开始“自我解决”,或者表现为其他怪异的方式。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.