码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论(第三版)练习 2.2-1 ~ 2.2-4 ( feat. 算法杂谈)

时间:2017-10-13 21:14:29      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:wap   ati   div   运行   针对   衡量   高中   基础上   swa   

1

我们先来观察几个简单的四则运算:

3 + 1 = 2 

23 + 23 = 46

2 + 4 = 6

上面几个式子有什么相似之处呢?

很显然它们的统一特征就是“求和”。我们找一个符号来抽象表示“这件事情”,比如说用 sum(a, b) 表示“求和”,

这样的话我们可以推出 sum(3, 1) = 2

sum(23, 23) = 46,

“ + ”只不过是个符号而已!

再比如我们需要把一些数组从小到大到排序。

例如说  1 3 2 ,很容易得到  1 2 3 

再比如  1 4 3  ,很容易得到 1 3 4

我们同样可以用一个符号来抽象表示这件事情, sort(1,  3, 2) 。 (sort 是英语中的排序)

 那我现在问你,你到底是如何把 1 3 2 从小到大到排序的呢?

按照普通高中生的思维,一般都会说:这还用想?#@X 把 3 和 2 调换就可以了。。

好吧 那我让你将 1729 237 9123 263 12 123 2813 123 213 123 321 312 3... 从小到大到排序你会怎么做呢?

▉▊▋▌▍▎▉▊▋▌▍▎▏█▇ ▆ ▅ ▄ ▃ ▂ ▂ 

▏█▇  请稍微思考一会儿。 ▌▍▎▇ ▆ 

▍▎▏▉▊▍▎▏▉▊▋▌▍▎▏▌▍▎█▌▍▎▌▍

是不是发现有特别多的方法?例如说你可以把最小的挑出来,然后再去找次小的、又或者可以按照排队的方法,把大的往后换...

当然,在我们软件开发的过程中要做的事情通常不是排序那么简单。

例如说一个非常简单的例子。。我希望你让计算机识别某张图片中的数字。。同样的,我们可以像 sum() 、sort() 一样把它抽象为 f(a.jpg) , f 只是个记号!

好吧,对于这个问题,我想非专业人员并不是很快可以知道该怎么做的。。。

我们把类似于 sum() 、sort() 、f(a.jpg) 的玩意儿叫做 “ 算法 ” ,我希望你可以建立一个更直观的理解。

 

2

大多数情况都不需要我们从头到尾亲自去设计一个算法,也就是你不需要去亲自弄清楚怎么样去识别图片中的数字。

更多时候,我们是作为一个算法的使用者,“识别数字”往往也只是软件功能的一小部分,

我们做得更多的事情是“分析算法”,然后拿来用:

要分析一个算法,首先需要我们能够看懂算法(),其次是能够甄别算法的效率。

WELL

我们怎样判断一个算法的效率呢?严格来讲一个算法的快慢相关于其具体的运行环境。

如果是真实的场景的话,肯定是要基于具体条件分析的。

但是从应用的角度,我们一般假设算法都运行在相同的环境下(诸如硬件条件、内存之类的),在此基础上去衡量算法的运行时间,这个运行时间对于不同的输入显然也不是一成不变的,排序 1 3 2 显然比排序 1729 237 9123 263 12 123 2813 123 213 123 321 312 3...快得多。

倘若赤裸裸的分析一个算法的话,运行时间指的是算法运行的步数哦!!!一般呈现这样的关系:运行时间相关于输入规模和输入内容, 

(当然,存在对于特定输入却有不同运行时间的状况,暂且不提)

通常认为,一个算法的增长量级越低就越有效,例如说n^2 相对于 nlogn 显得很笨重!

具体怎么算参考算法导论。

 

扯那么多,我其实是想说:分析算法特别.特别.特别重要!!!你可以不知道各种各样的算法的具体实现(这没必要,通常也不现实!),但是它们有什么用、效率怎么样总应该要懂吧?而搞懂这一切的诀窍、捷径就是去分析.大量.算法,当然不是叫你把每行代码都搞得很清楚(那是算法研究员搞的。。),重点是上面的两点!—— 有什么用、效率怎么样

 

// 以上观点偏主观,所以。。仁者见仁吧。:p

 

2.2-1

theta n^3

 

2.2-2

SELECTION-SORT(A)
    for i = 1 to A.length-1
        for j = i+1 to A.length
            if A[i] > A[j]
                swap(A[i], A[j])

维持的循环不变式是 A[1..i] 按序排列(从小到大),

非形式化,不太严谨地证明一下:

初始化:对于单个元素 A[1],显然成立。

保持:我们假设在 i = n 时循环不变式成立,那么当 i = n + 1 时,A[i] 将会和 A[i+1] ~ A[A.length] 中的每个元素进行比较,最终 A[i] 将取得它们中的最小值,事实上它就是在整个序列中次小于 A[i-1] 的那个数(因为每次迭代总会拿到剩余队列的最小值,因此“下一次”只能拿到仅次于“上次”的最小值),故 A[1..i] 保持循环不变式。

终止:当 i = A.length 时迭代结束,根据上面的证明 A[1..A.length-1] 已确保有序, A[A.length] 是经过 A.length - 1 次比较后剩下的次次次..(省略 A.length - 4 个次).次最小数,也就是序列中的最大数,因此 A[1.. A.length] 按序排列,故算法正确。 

算法的运行时间 T(n) = c1*(n-1) + c2*(n-1+1)*n / 2 + c3*(n-1+1)*n / 2 + c4*(n-1+1)*n / 2

最佳状况是数组已经有序(c4 取 0),最坏情况是数组逆序(如上式),不过两者增长量级是相同的,都是 theta n^2 。

 

2.2-3

平均需要检查 n / 2 个元素,最坏情况需要检查 n 个。

平均情况和最坏情况的增长量级都是 theta n 

SEARCH(v, A)
    for i = 1 to A.length    c1 tn
        if A[i] == v        c2 tn
            return i        c3 1 or 0
    return NIL                c4 1 or 0  

T(n) = c1*tn + c2*tn + c3 + c4

代入 n (最坏)或者 n/2 (平均),忽略常数,结果都是 theta n

 

2.2-4

针对特殊情况进行测试,如果符合的话就直接给出预先计算好的答案。

就是增加常数时间能跑完的代码,用于覆盖一些特例,减少无所谓的循环。

下面是网上找的参考答案:

技术分享

 

// 以上纯属个人观点,若有什么不恰当(或者给人产生误导)之处,麻烦指正哦 ~~ 

算法导论(第三版)练习 2.2-1 ~ 2.2-4 ( feat. 算法杂谈)

标签:wap   ati   div   运行   针对   衡量   高中   基础上   swa   

原文地址:http://www.cnblogs.com/xkxf/p/7659961.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!