【问题标题】:Learning efficient algorithms学习高效算法
【发布时间】:2011-03-12 14:05:16
【问题描述】:

到目前为止,我主要集中在如何正确设计代码,使其尽可能可读和可维护。所以我一直选择学习更高层次的编程细节,比如类交互、API设计等。

我从未真正觉得特别有趣的算法。结果,即使我可以为我的程序提出一个好的设计,即使我可以为给定的问题提出一个解决方案,它也很少是最有效的。

是否有一种特殊的思考问题的方式可以帮助您想出尽可能有效的解决方案,或者只是练习和/或记忆的简单问题?

另外,您可以推荐哪些在线资源来教您针对不同问题的各种有效算法?

【问题讨论】:

  • 更多细节:我不是在谈论设计模式、如何遍历树以及其他常见的东西。我正在寻找的一个例子是:你有一个数字列表,你知道其中只有一个是唯一的(其他的都出现了两次)。您必须确定 O(n) 中的唯一数字:您使用 XOR 操作。
  • 这是解决 Project Euler 式问题的好方法,但您在日常工作中遇到过这种问题吗?
  • @larsmans 我意识到这不是你在现实世界场景中遇到的东西,但肯定(以某种不同的形式)它有用途(对吗?)。当只涉及逻辑时,我认为自己能够编写其他高效的程序,但我并不擅长有效地解决这类抽象问题。 (我在读高中,我没有工作。:))
  • 啊哈。嗯,一些更“异国情调”的算法确实不时出现(鸽巢排序、Boyer-Moore 多数投票、字符串搜索的东西),但我坚持我的观点,即数据结构更为重要。如果有任何书籍或教程教你没有数据结构的算法,那么它可能不值得一读。

标签: algorithm complexity-theory


【解决方案1】:

数据占主导地位。如果您围绕正确的抽象数据结构 (ADT) 设计您的程序,您通常会得到一个干净的设计,算法会很自然地遵循,当性能不足时,您应该能够“插入”更高效的算法。

强大的数学和逻辑背景在这里会有所帮助,因为它允许您将程序作为函数、集合、图形、序列等之间的交互在高层次上进行可视化。然后您可以决定是否需要对集合进行排序 (平衡 BST,O(lg n) 操作)与否(哈希表,O(1) 操作),序列需要支持哪些操作(类向量或类列表)等。

如果您想学习一些算法,请买一本好书,例如 Cormen 等人。并尝试实现主要的数据结构:

  • 二叉搜索树
  • 通用二叉搜索树(不仅仅适用于int 或字符串)
  • 哈希表
  • 优先队列/堆
  • 动态数组

【讨论】:

  • 我完全同意。干净的编码有助于抽象出真正的底层算法(即“实现细节”)。因此,您阅读一本好书(例如 Cormen)与编写代码是正交的。
【解决方案2】:

Introduction To Algorithms 是一本让您思考不同算法/数据结构的效率的好书。

本书的作者还在 MIT 教授算法课程。你可以找到大部分讲座here

【讨论】:

    【解决方案3】:

    我想说,在提出好的算法(恕我直言,这实际上是好的设计的一部分)时,您必须开发一种思维方式。这最好通过研究算法设计来完成。我所说的学习并不是指仅仅了解教科书中涵盖的所有常见算法,而是要真正了解它们的工作原理和原因,并能够将其中包含的基本思想应用于您要解决的实际问题。

    我建议阅读一本关于算法的好书(我最喜欢的是 CLRS)。对于在线资源,我会推荐TopCoder Algorithm Tutorials 中的系列文章。

    我不明白你为什么会同时提到练习和记忆。记忆对你一点帮助都没有(你可能已经知道了),但练习是必不可少的。如果你不能应用你学到的东西,那它就不是真正的学习。您可以在SPOJProject EulerPythonChallenge 等各种在线编程竞赛/拼图网站上练习。

    【讨论】:

    • +1 用于链接算法设计和程序设计。将 Knuth 的“万恶之根”引语断章取意太容易了。好的程序甚至是好的界面都应该兼顾正确性和速度。
    【解决方案4】:

    建议: 首先,我推荐“算法介绍,Corman 的第二版”一书,这本书包含了您需要的大部分(如果不是全部)算法。 (一些更重要的主题是排序算法、最短路径、动态规划、许多数据结构,如 bst、哈希映射、堆)。

    另一种学习算法的好方法是http://ace.delos.com/usacogate,开始后很好的练习。

    对于您的问题,您将习惯于编写快速运行的良好代码,经过一些练习后您就不想编写效率低下的代码了。

    【讨论】:

    • USACO 非常适合在很短的时间内学习如何解决 NP 完全问题,但它与软件工程中的实际问题关系不大。
    • 这本书不仅仅是介绍。
    【解决方案5】:

    虽然我认为 @larsmans 是正确的,因为理解逻辑和数学是理解如何选择有用的 ADT 来解决给定问题的快速方法,但研究现有解决方案可能对我们这些在这些主题上苦苦挣扎的人更有指导意义。尤其是审查已建立的软件 (OSS) 的代码,以解决与您感兴趣的问题类似的问题。

    我发现这种学习方法的一个特别好的方法是审查这样一个项目的单元测试。例如,Apache Lucene 有一个包含大量示例的源代码控制存储库。虽然它没有揭示底层算法,但它有助于追踪解决特定问题的特定功能。这为研究其内部结构提供了机会——即一种有趣的算法。在 Lucene 的情况下,inverted indices 浮现在脑海中。

    虽然这并不能保证您发现的算法是最好的,但它很可能已经受到了很多审查,并且可能来自带有积极邮件的项目,可以回答您的问题。因此,它是寻找可能比我们大多数人自己想出的解决方案更好的解决方案的好资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 2018-10-01
      • 2020-08-08
      • 2011-08-01
      • 1970-01-01
      • 2010-09-27
      • 2020-02-27
      相关资源
      最近更新 更多