• 2007-01-24

    乱弹算法

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/4370771.html

    我们有时会说,一个人不会做事,其实并不是说这个人做的事不对,而是说这个做事的方法没有条理或是显得笨拙。做事的方法在程序设计中就是算法,同样一件事,选择不同算法显现的结果就是截然不同的。

    举个简单的例子,如何判断一个数是2的幂。

    最直观的想法当然是用这个数不断的除以2,看是否能除干净。这样做保证没有错,但通常最直观的想法之外还会有更好的解决方案。我们知道,在计算机中数是以二进制形式保存的,而2的幂有一个特征,就是只有一个1,剩余位全是0。知道这些之后,我们就可以统计一下这个数里面1的个数,如果为1,就是2的幂。统计1的个数,我们通常会用位运算的方式进行,而前面的方法中会用到除法,作为程序员,我们很清楚除法在计算机中的杀伤力,所以,也很容易看出第二种方法较之第一种方法的进步。是不是这样这个问题就算完美的解决了呢?

    在我知识所及的范围内,这个问题还有一个更好的答案。前面说过了,当一个数是2的幂时,它只有一个1,这样如果把它减1,得到的就是原来为1的位成了0,而其后的所有位都变成了1,这样把它们与在一起,得到结果应该是0,也就是:
        n & (n - 1) == 0

    这是O(1)的算法,比之统计1的方法显然要更好一些。

    同样的事,采用不同的方法,效果会有很大的差别,这就是算法的力量。很多时候,看到一个精妙的解决方案,拍案叫绝的同时,我们并不会觉得如何难理解,反而会想,我为什么没想到,差别就在于此。事实上,我们所遇到的大多数问题都是这样,如果单以解决方案来看,没有任何难以理解的地方,但它确实不像看起来那么容易想到。不过,即便再简单的解决方案,不懂这个算法,单独来看代码,反而会云里雾里,就像前面那个算法,直接拿到代码,说是判断2的幂的代码,真是够理解一阵子的。当然,这是简单的情况,我真的经历过,在不理解算法的情况下看代码,完全不知所云的感觉。

    所谓学习算法,是学习那些名词,背诵那些现成的算法吗?我不这样认为,说句实话,开发中遇到恰好需要用书上的算法去解决实际问题的机会少之又少,而那些叫做数据结构的东西基本上都有现成的程序库可用。同那些为了参加竞赛而学习算法的同学们不同,我们学习算法的目的是为了更好的解决问题。

    学习算法要掌握一些已有问题的最佳答案,这样,我们遇到类似的问题,便不会在去绕弯路。或许,经过自己的探索,我们可以找到最佳方案,但是实在没有必要为一些已有经典算法的问题浪费时间。

    学习算法更要掌握解决问题的方式,也就是说除了鱼,我们还要渔。开发中,我们总会遇到“新鲜”的问题,这时我们没有现成的答案可以参考。这时,通过学习算法所掌握的解决问题的方法就开始发挥其功效,如何分解问题,如何降低算法复杂度等等。事实上,解决问题的方法更重要一些。

    记得JavaEye曾经有个帖子谈论到TAOCP,大家普遍的感慨是,真希望有时间静下心来好好学习一下算法,无情的现实告诉我们,对于已经工作的我们来说,这几乎是不可能的。所以,只能寄望于自己去挤时间去学习。

    单独学习算法本身也是很枯燥的,如果能和自己遇到的问题结合起来,或许效果会好一些。我有一段时间在做视频压缩中运动估计算法,其主要的作用就是在一幅图像中去找与另一副图像某一块最匹配的块。在这个过程中,我见识了几个不同的算法,看到很多为了优化所做的调整。回想之前一些同事所做的类似的工作,高下立判。

    结束之前,推荐一篇我比较喜欢的文章,《一切从游戏开始》,跟着它体会一下算法的美妙吧!

    分享到:

    历史上的今天:

    Mini CodeJam 2010-01-24
    引用地址:

    评论

  • 在编程之美上面看到这个题了,这个算法好像很流行
  • 有道理,计算机工作者最基本的素质我想是要学会计算思维,算法是一种训练的方式,训练我们适应这种思维,这是我的理解
  • 收益非浅