对于“天真实施”,计算机科学家所说的最清楚的解释是什么?我需要一个很好的明确的例子,它可以说明 - 理想情况下,即使是非技术人员 - 天真的实现可能技术上是问题的有效解决方案,但实际上是完全无法使用。
答案 0 :(得分:71)
我会尽量远离计算机。询问听众他们如何在字典中找到条目。 (正常的单词定义词典。)
天真的实现是从一开始就开始,看看第一个单词。哦,那不是我们要找的那个词 - 看下一个,等等。值得向观众指出他们可能甚至没有想到这种做事方式 - 我们'足够聪明,可立即打折!然而,这是你能想到的最简单的方式。 (询问他们是否可以想到更简单的东西可能会很有趣,并检查他们是否真的理解为什么它比我们实际做的更简单。)
下一个实现(和一个非常好的实现)是从字典中间开始。我们要找的那个词是在之前还是之后?如果是之前,请转到开始和我们现在之间的中间页面 - 否则,转到我们现在和结束之间的页面,等等 - 二进制印章。
实际的人类实现是利用我们的信件知识快速到达“几乎正确的地方” - 如果我们看到“大象”,那么我们就会知道它将“接近开始”可能大约1 / 5号通过。一旦我们到达E(我们可以进行非常非常简单的比较),我们就会找到EL等。
答案 1 :(得分:7)
StackOverflow的杰夫阿特伍德有一个great example一个与洗牌相关的天真算法。
答案 2 :(得分:4)
以最直接,最棘手的方式做到这一点。一个例子是选择排序。
在这种情况下,天真的不意味着不好或无法使用。这只是意味着不是特别好。
将Jon Skeet's advice铭记于心,您可以将选择排序描述为:
这很容易理解,但不一定是最好的。
答案 3 :(得分:3)
另一个天真的实现是在命令式语言中使用递归来计算整数的阶乘。在这种情况下,更有效的解决方案是使用循环。
答案 4 :(得分:2)
你能想到的最明显,最天真的求幂算法是什么?
base ** exp
为base * base * ... * base
,exp
次:
double pow(double base, int exp) {
double result = 1;
for (int i = 0; i < exp; i++)
result *= base;
return result;
}
但是,它并没有处理负指数。记住base ** exp == 1 / base ** (-exp) == (1 / base) ** (-exp)
:
double pow(double base, int exp) {
double result = 1;
if (exp < 0) {
base = 1 / base;
exp = -exp;
}
for (int i = 0; i < exp; i++)
result *= base;
return result;
}
实际上,有可能计算base ** exp
的乘法次数少于exp
!
double pow(double base, int exp) {
double result = 1;
if (exp < 0) {
base = 1 / base;
exp = -exp;
}
while (exp) {
if (exp % 2) {
result *= base;
exp--;
}
else {
base *= base;
exp /= 2;
}
}
return result * base;
}
这利用了base ** exp == (base * base) ** (exp / 2)
如果exp
是偶数,并且只需要log2(exp)
次乘法的事实。
答案 5 :(得分:2)
我花时间仔细阅读你的问题,我有一个完美的例子。
一个很好的明显例子,它可以说明 - 理想情况下,甚至是非技术人员 - 天真的实现可能技术上是问题的有效解决方案,但实际上完全无法使用。
试试Bogosort!
如果使用bogosort对一副牌进行分类,它将包括检查牌组是否有序,如果不是,则将牌组扔到空中,随机拿起牌,以及重复这个过程,直到甲板被分拣。
答案 6 :(得分:2)
“天真实施”几乎总是“蛮力实施”的同义词。天真的实现通常是直观的,并且是第一个想到的,但也经常是O(n ^ 2)或更糟,因此对于大输入来说太长也太实用了。
编程竞赛充满了问题,其中天真的实现将无法在可接受的时间内运行,问题的核心是提出一种改进的算法,该算法通常不那么明显,但运行速度要快得多。 / p>
答案 7 :(得分:1)
确定数字是否为素数(素性测试)是一个很好的例子。
天真的方法只检查n mod x,其中x = 2..square root(n)对于至少一个x是零。对于非常大的素数,这种方法可能变得非常慢,并且在密码学中使用是不可行的。
另一方面,有一些概率或快速确定性测试。这些内容太复杂,无法解释,但您可能需要查看有关该主题的相关维基百科文章以获取更多信息:http://en.wikipedia.org/wiki/Primality_test
答案 8 :(得分:1)
假设有人想出如何从数据库中提取单个字段,然后继续用PHP编写网页或者在页面上为每个字段对数据库进行单独查询的任何语言。它可行,但速度极慢,效率低,难以维护。
答案 9 :(得分:1)
天真并不意味着不好或无法使用 - 这意味着具有某些特定情况在特定情境和中出于特定目的。
经典的例子当然是排序。在排序十个数字列表的上下文中,任何旧算法(除了pogo排序)都可以很好地工作。然而,当我们达到数千或更多的数量级时,通常我们说选择排序是天真的算法,因为它具有O(n ^ 2)时间的质量,这对于我们的目的来说太慢了,并且非天真算法是快速排序,因为它具有O(n lg n)时间的质量,这对于我们的目的来说足够快。
事实上,可以说在排序十个数字列表的情况下,快速排序是一种天真的算法,因为它需要比选择排序更长的时间。
答案 10 :(得分:1)
天真的实施是:
答案 11 :(得分:0)
冒泡排序超过100,000,000条。
答案 12 :(得分:0)
您通常用来对一副牌(insertion sort或selection sort进行排序(O(n ^ 2))的直观算法可以被认为是天真的,因为它们易于学习和实施,但是不能很好地扩展到100000张卡片:D。在一般设置中,有更快的(O(n log n))方法对列表进行排序。
但请注意,天真并不一定意味着错误。在某些情况下,插入排序是一个不错的选择(例如,当你有一个已经排序的大牌并且几张未分类的牌要添加时)。
答案 13 :(得分:0)
(还没有看到真正天真的实施,所以...)
以下实现是“天真的”,因为它不包括边缘情况,并且在其他情况下会中断。理解起来非常简单,并且可以传达编程信息。
def naive_inverse(x):
return 1/x
它会:
通过添加这些功能,您可以使其更加“成熟”。
答案 14 :(得分:-5)
O(n!)算法。
foreach(object o in set1)
{
foreach(object p in set1)
{
// codez
}
}
对于较小的集合,这将表现良好,然后对于较大的集合则表现较差。
另一个可能是一个天真的单身人士,不考虑线程。
public static SomeObject Instance
{
get
{
if(obj == null)
{
obj = new SomeObject();
}
return obj;
}
}
如果两个线程同时访问它,那么它们可能会获得两个不同的版本。导致严重怪异的错误。