1700507480
1700507481
在这个例子中我们发现了一个现象:虽然时间复杂度是O(nn),但是花费的时间并非如此。在测量中也发现:单次试探的时间每次下降为之前的0.18倍左右。也就是说,当N=15时,我们还没有找出这条渐近线的极限。没关系,下面这两个结论已经很重要了。
1700507482
1700507483
结论1:时间复杂度的增加和实际运算的时间增加不成比例
1700507484
1700507485
千万不要“望文生义”,想当然地认为时间的增加和迭代次数成正比。具体的消耗时间需要通过实际的测量得到,这种方法更为准确。在其他算法场合下,可以用更大的N来尝试,例如1000、5000、10000、50000……这样的序列。对这些点的测量会给那些位于这些点之间的未测量的N的场景提供一个参考刻度。
1700507486
1700507487
结论2:如果可能,尽量测出这个极限的位置
1700507488
1700507489
也就是说,在合理的时间成本范围内尽量测出最后不再下降的单次试探时间。例如,连续2次增加N,都发现单次试探时间不再有明显下降,即可考虑给出这样的结论:可以作为更大的N出现时所花费时间的评估基础。
1700507490
1700507491
如果要在一个庞大的分布式集群里对未知节点上的某一条数据进行查找,在没有索引的情况下,使用的同样是典型的穷举法。别以为所有的查找场景情况下都会有索引,索引的建立和维护是有成本的,无论是OLAP系统,还是OLTP系统,对索引的使用都是比较谨慎的。
1700507492
1700507493
再如,在没有任何提示的情况下破解一个密码也是典型的穷举法使用场景——必须一个一个试过,才会知道这个密码是否与正确的密码吻合。
1700507494
1700507495
穷举法适用于数据量小、硬件极为丰富或信息预处理不充分的场景。要事先根据经验或实际的时间消耗测算来预估破解的总时长,以判断是否可以使用穷举法。
1700507496
1700507497
1700507498
1700507499
1700507501
数据科学家养成手册 11.4 分治法——化繁为简
1700507502
1700507503
分治法的应用在生产中更为普及,而且这种思路可以说同样是浑然天成——也是人类自己处理复杂问题的逻辑。人类在碰到一个庞大而复杂的问题时同样会想:这个问题可不可以分解成多个简单一些的小问题?每个问题获解了,整体就获解了(如图11-10所示)。
1700507504
1700507505
1700507506
1700507507
1700507508
图11-10 问题分解
1700507509
1700507510
这种思维方式的一个好处是可以降低求解难度。在日常生活中我们知道,处理1个对象事物和处理10个对象事物的成本不是10倍的关系。举个现实生活中的例子,一个人自己做饭吃,翻翻电冰箱,有些鸡蛋和西红柿,炒个鸡蛋西红柿凑合凑合就行了;而如果10个人一起聚餐,即使有足够的鸡蛋和西红柿,也不能炒10倍量的鸡蛋西红柿大家一起凑合,要采买的蔬菜和肉类多了,准备工作复杂了,花费的时间成本也就高了。这里的成本关系不是线性的,这种方式对一个人来说处理的成本太高了。怎么办?最好的办法就是事先商量好,每个参加聚餐的人都带一个做好的菜——人数越多,效果越明显。这种方式的处理结果就是每个人的时间成本略有增加,但是不会把其中一个人累死——开个玩笑。
1700507511
1700507512
在经典的单机应用场景中,也有一些算法应用了分治法。例如,二分查找、多路归并排序、大整数乘法等,都是典型的把复杂问题简化为局部与局部之间的简单问题获解进而得到全局解的思路。
1700507513
1700507514
这种思路在其他更宏观的场景中一样可以见到。例如,在一个1PB的数据集中,要查找其中的最大值。这种数据在一台计算机上怎么存储都是个问题,即使能存储,也要一部分一部分地把数据提取到内存中进行排序,找出最大值,然后将每次迭代的最大值保留,与下一次迭代的最大值相比较,保留两者中较大的值,直到遍历1PB的数据为止。
1700507515
1700507516
这种办法几乎只是理论上可行,因为它所消耗的时间成本极其高昂。而在大型的Hadoop集群中,可以在几百甚至几千个节点上分别查找,每个节点只要找到本节点上的最大值,最后找出这些值中的最大值,就能获解。这种任务的加速几乎是随着集群规模的增加而线性加快的(如图11-11所示)。对海量数据处理来说,Hadoop框架的解决方案本质上就是分治法的应用。
1700507517
1700507518
1700507519
1700507520
1700507521
图11-11 Hadoop中各map/reduce分治执行任务
1700507522
1700507523
不仅如此,程序员熟悉的OOP技术(Object Oriented Programming,面向对象编程)和过去使用的POP技术(Procedure Oriented Programming,面向过程编程)的设计思路也有分治思想的深刻烙印。
1700507524
1700507525
在一个类的设计中,除了在必要的对外服务功能部分用public的方式暴露出来以外,其他的内容都在内部用protected方式或private方式进行保护(如表11-5所示)。
1700507526
1700507527
表11-5 面向对象的不同使用权限
1700507528
1700507529
[
上一页 ]
[ :1.70050748e+09 ]
[
下一页 ]