那么 - 最近你“发现”了哪些激动人心的算法?

时间:2008-10-05 19:33:49

标签: algorithm language-agnostic

我喜欢阅读有关新的和聪明的算法。我喜欢开箱即用,因此欢迎来自各个计算领域的各种算法。

我不时阅读研究论文以跟上当前的研究并拓展我的视野。我也想学习新的技巧。不幸的是,我倾向于只关注我感兴趣的领域,所以我想念很多有用的东西。

让我们不要发布主流的东西。而是写一些特别的东西让你思考:“哇 - 现在那是一个聪明的解决方案!”。

10 个答案:

答案 0 :(得分:12)

我将从每个人都可以使用的东西开始:内省排序。 http://en.wikipedia.org/wiki/Introsort

一种新的排序算法,它结合了最佳的快速,插入和堆排序。确切地说,它本身不是一种新算法,而是一种非常聪明的组合。

您可以快速排序到快速排序进入退化O(n²)情况的速度。这几乎没有成本检测到。剩余分区使用heap-或merge-sort进行排序。这不仅避免了退化的情况,而且还为堆栈使用创建了明确定义的上限。

插入排序 - 像往常一样 - 关注快速排序传递中遗留的所有小分区。

对我来说这是一个新发现,因为我停止对我的应用程序使用快速排序。

我在嵌入式设备上做了很多工作,我不得不关心堆栈的使用。使用快速排序总是有点冒险,因为它运行的机会很小。即使您知道使用当前数据一切都会很好,您永远不会知道是否有人后来将您的代码切换到一个不同的项目中,并将其用于数据,而这些数据从未实现过。

由于内省排序,我现在可以完全控制堆栈使用并获得性能提升。

答案 1 :(得分:9)

这不是全新或令人兴奋的事情,但我喜欢Levenshtein Distance

Levenshtein Distance通常被称为两个字符串之间的编辑距离,它基本上是一个度量,通过计算将一个字符串转换为另一个字符串的最小操作数来测量两个字符串之间的差异

我正在使用此算法建议对多个字符串进行排序,以匹配(可能是不同的)字符串的外部源的顺序。

答案 2 :(得分:5)

我最近重新发现了用于整数平方根的旧Marchant计算器算法的二进制变体。没有乘法或除法,只有加法,减法和移位。对不起,我丢失了参考资料:

def assert
  raise "Assertion failed !" if $DEBUG and not yield
end

def sqrt(v)
    value = v.abs
    residue = value
    root = 0
    onebit = 1
    onebit <<= 8 while (onebit < residue)
    onebit >>= 2 while (onebit > residue)
    while (onebit > 0)
        x = root + onebit
        if (residue >= x) then
            residue -= x
            root = x + onebit
        end
        root >>= 1
        onebit >>= 2
    end
    assert {value == (root**2+residue)}
    assert {value < ((root+1)**2)}
    return [root,residue]
end

$DEBUG = true

a = sqrt(4141290379431273280)
puts a.inspect

非常抱歉,忘记说这是Ruby,对于那些不熟悉的人。

答案 3 :(得分:4)

我一直认为Quake中的magic square-root函数非常聪明。它非常快,因为它避免了任何较慢的操作,例如除法等。

float SquareRootFloat(float num) {
    long i;
    float x, y;
    const float f = 1.5F;

    x = num * 0.5F;
    y  = num;
    i  = * ( long * ) &y;
    i  = 0x5f3759df - ( i >> 1 );
    y  = * ( float * ) &i;
    y  = y * ( f - ( x * y * y ) );
    y  = y * ( f - ( x * y * y ) );
    return num * y;
}

他还有一个相关的magic inverse square-root

答案 4 :(得分:3)

这是我最近“发现”的Viterbi algorithm的实现。这里的目的是确定视频编码中帧类型的最佳分布。维特比有时候有点难以理解,所以我认为最好的方法是通过实际的例子。

在此示例中,最大连续B帧为2.所有路径必须以P帧结束。

路径长度1给我们P作为我们的最佳路径,因为所有路径必须以P帧结束,没有其他选择。

路径长度2为我们提供BP_P"_"是长度1的最佳路径。 这为我们提供了BPPP。现在,我们计算实际成本。 让我们说,为了这个例子,BP是最好的。

路径长度3为我们提供BBP_B P和__P"__"是长度为2的最佳路径。 这为我们提供了BBPPBP以及BPP。现在,我们计算实际成本。 让我们说,为了这个例子,BBP是最好的。

路径长度4为我们提供了_BBP__BP以及___P"___"是长度为3的最佳路径。 这给了我们PBBP和BPBP以及BBPP。现在,我们计算实际成本。 让我们说,为了这个例子,BPBP是最好的。

路径长度4为我们提供了__BBP___BP以及____P"____"是长度为4的最佳路径。 这为我们提供了BPBBPBBPBP以及BPBPP

现在 - 等一下 - 所有路径都同意第一帧是B!所以第一帧是B

重复处理,直到他们同意哪个帧是第一个P帧,然后开始编码。

该算法可以适应许多领域的各种问题;它也与我在this post中提到的算法相同。

答案 5 :(得分:3)

当我得知Burrows-Wheeler block sorting algorithm进行数据压缩(在bzip2中使用)时,我印象深刻。令人惊讶的是,分拣步骤是可逆的!

答案 6 :(得分:3)

生物信息学充满了以奇怪形式产生大量数据的实验案例,需要富有想象力的算法来处理。

an introduction to bioinformatics algorithms对于这类内容非常精彩

答案 7 :(得分:3)

Dynamic programming充分利用optimal control problems。很清爽。

答案 8 :(得分:1)

它并不像其他人那样华而不实,但它派上用场了:

((m+n) + (m-n)) / 2 === m (for any two real numbers m and n)

我在SQL中使用了一些聚合查询逻辑来计算项目的评级。评级为+1和-1。我只需要知道评分总数及其总和的正评分数(m)。

使用此逻辑确实加快了查询速度,并允许我返回0评级项目的结果。

(我没有选择+1和-1;我继承了那个。)

答案 9 :(得分:-1)

我发现这非常有用,证明a ^ n = b ^ n + c ^ n但仅适用于n = 2 不幸的是,这个评论框太小而无法包含它!