note/grokking_algorithms.md
Leigh Caldwell 在 Stack Overflow 上说的一句话,“如果使用循环,程序的性能可能更高;如果使用递归,程序可能更容易理解。如何选择要看什么对你来说更重要。”
Haskell 等函数式编程语言就没有循环,因此你只能使用递归来编写这样的函数。如果你对递归有深入的认识,函数式编程语言学习起来将更加容易。如果你喜欢递归或者想学习一门新语言,可以研究一下 Haskell。
散列表要避免冲突,需要有:
有向图中的边为箭头,箭头的方向指定了关系的方向。无向图中的边不带箭头,其中的关系是双向的。
广度优先搜索求最短路径,对于检查过的点,务必不要再去检查,否则会导致无限循环。
在无向图中,每条边都是一个环。迪杰斯特拉算法只能用于有向无环图(directed acyclic graph, DAG),如果有负权边,就不能使用迪杰斯特拉算法。
在有负权边的图中,要求最短路径,需要用到贝尔曼-福德算法(Bellman-Ford algorithm)
贪心算法的理念:每步都采取最优解。每步都选择局部最优解,最终得到的就是全局最优解。
判断是否是 NP 完全问题
对于 NP 完全问题,还没有找到快速解决方案。
面临 NP 完全问题,最佳的做法是使用近似算法。
仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用。
每种动态规则解决方案都涉及网格。
没有放之四海皆准的计算动态规划的公式,动态规划是一门艺术。
git diff 命令指出两个文件的差异,使用的就是动态规划实现的。
布隆过滤器是一个概率型数据结构,它提供的答案有可能不对,但很可能是正确的。可能出现错报的情况,但是不可能出现漏报的情况。布隆过滤器非常适合用于不要求答案绝对准确的情况。
面临海量数据且只要求答案八九不离十时,可考虑使用概率型算法。
当前最安全的密码散列函数是 bcrypt,但没有任何东西是万无一失的。
SHA 散列函数是局部不敏感的,有一个字符变化,都会导致其散列值截然不同。有时候希望散列函数是局部敏感的。在这种情况下,可使用 Simhash。如果你对字符串做细微的修改,Simhash 生成的散列值也只存在细微的差别。这让你能够通过比较散列值来判断两个字符串的相似程度。需要检查两项内容的相似程序时,Simhash 很有用。