算法知识还是需要地……

一般情况,我们遇到真正的算法问题,似乎并不多,大都是检索、增删改之类的操作和功能点,只要对语言,如 JavaScript 和 C# 或 Java 特性足够了解,都很容易解决。但若是遇到真正的算法问题,足够让人想两三天的。此时,就是体现你价值的地方啦……

其实,本文内容并不新鲜,只是重新整合后,会呈现出不同的意义。通过两个计算,展示程序员不能忽视算法方面的知识,如何利用分治法、动态规划、贪心算法等思想设计自己的算法,并能大概分析,了解其“瓶颈”,在何种情况下,运行效率最好。

你可以是什么都懂的程序员,可别人不用听你口若悬河地大谈各种技术,只要看下你的代码,就知道了。

最近,编写一个工厂生产过程中变更工艺的算法。关键是,无论工艺怎样变更,数量不能错(包括零件数量、可排序数量、已排产数量、返修数量、报废数量)。甲方认为几乎不能实现。因为,变更的情况太多,几乎无法处理,即便处理了,算法的判断会不计其数。表面看起来的确如此,但从数学上,如此多的情况都可以合并成一个计算公式,只要找到它。再利用一点算法的知识,在递归条件上考虑一下。最后的核心算法:三个递归函数,每个函数不过 10 行,显得很优雅。而且,通过把代价考虑进去,可以扩展该算法。

在此之前,2008 年毕业,我使用 VS C# 开发 Web 应用程序……到 2012 年,只跳槽一次。这期间,我写过较复杂的算法,是在之前公司做的一个关于解析数据的功能和算法。因此,当我愤然离职后,决定将核心算法的备注删掉一半。皮鞭蘸凉水,累死你们,呵呵~~

数据是关于气象、水文、台站、浮标、生物、化学、重力、磁力、地球物理、悬浮体等这些基础数据,6 个大类,里边的小类无数……这些数据都是由相关器械采集并生成的 DAT 文件,特点:

  • 每种数据有自己的书写格式;
  • 有横向书写,也有竖向书写;
  • 用 UltraEdit 查看,每列有具体的含义;
  • 数据有详细、严格的要求,比如精度、长度、科学计数法等;
  • 数据后面有单位符号;  
  • 多个行的数据可能存在关系。因为,DAT 数据对应数据库多个表等等。

这个功能用策略模式。用反射创建相应的解析器。关键是将数据库中的数据恢复成 DAT 文件的算法。将数据格式设置成 XML 文件(XML 文件是 DAT 文件与数据库表和字段的映射关系),既要递归格式,也要递归数据;另外,还要设置队列,递归前或递归后,要对数据进行处理等等。

 

问题一


我们知道插入排序和合并排序的时间复杂度分别为 O(n^2)O(nlgn),后者比前者增长的慢。因此,当输入 n 规模越来越大时,合并排序比插入排序会有更好的效果。

假设,在同一台机器上比较插入排序和合并排序的实现。若输入规模为 n,前者要做 8n^2 步,后者要做 64nlgn 步。那么,n 取何值时,插入排序将优于合并排序?

超越方程

其中,

  • clip_image002[5]”表示“等价于”;
  • clip_image002[3]”是超越方程(transcendental equation)。这样的方程存在无法用自变量的多项式或开方表示的函数。超越方程无法利用代数几何来求解,沒有一般的求解公式,也很难得到解析解。与超越方程相对的是代数方程。但可以写程序解这个不等式方程。
// 显然 n 从 2 开始
int n = 2;
double insert = Math.Pow(2, n);
double meger = Math.Pow(n, 8);
 
while (insert <= meger)
{
    Console.WriteLine(string.Format("n={0},INSERT={1},MERGE={2}", n, insert, meger));
    n++;
    insert = Math.Pow(2, n);
    meger = Math.Pow(n, 8);
}
Console.WriteLine(string.Format("n={0},INSERT={1},MERGE={2}", n, insert, meger));

1

n=44 时,插入排序的步骤就开始大于合并排序。因此,n [2,43]

 

问题二


上面,当输入 n 规模不断变大时,插入排序和各并排序的差异。因此,往往为解决同一个问题而设计的各种算法在效率上会有很大差异。这些差异可能比个人微型计算机与巨型计算机之间的差异还要大。

例如,让一台巨型计算机做插入排序,而让另一台微型计算机做合并排序,它们的输入都是一个长度为 10^6 (100 万)的数组。假设,巨型计算机每秒执行 10^8 (1 亿)条指令,微型计算机每秒仅仅为 10^6 (100 万)条指令。为了使差异更明显。假设,世界上最优秀的程序员用机器代码在巨型计算机上实现插入排序,编写的程序需要执行 2n^2 条指令排序 n 个数。另一方面,让一个一般程序员在微型计算机上用高级语言编写合并排序,代码要执行 50nlgn 条指令。

为了排序 10^6 万个数,巨型计算机耗时:

clip_image002[30]

而个人微型计算机耗时:

clip_image002[36]

可以看出,由于采用更低阶的算法,即使是用低效的编译器,微型计算机还是比巨型计算机快 20 倍。

备注:

对数以 2 为底。

posted @ 2012-06-30 15:02  船长&CAP  阅读(439)  评论(0编辑  收藏  举报
免费流量统计软件