zoukankan      html  css  js  c++  java
  • 算法导论(第三版)练习 2.2-1 ~ 2.2-4

    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

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

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

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

    摘:

    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 把 32 调换就可以了。。
    
    好吧 那我让你将 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
    大多数情况都不需要我们从头到尾亲自去设计一个算法,也就是你不需要去亲自弄清楚怎么样去识别图片中的数字。
    
    更多时候,我们是作为一个算法的使用者,“识别数字”往往也只是软件功能的一小部分,
    
    我们做得更多的事情是“分析算法”,然后拿来用:
    
    要分析一个算法,首先需要我们能够看懂算法(),其次是能够甄别算法的效率。
    
     
    
    我们怎样判断一个算法的效率呢?严格来讲一个算法的快慢相关于其具体的运行环境。
    
    如果是真实的场景的话,肯定是要基于具体条件分析的。
    
    但是从应用的角度,我们一般假设算法都运行在相同的环境下(诸如硬件条件、内存之类的),在此基础上去衡量算法的运行时间,这个运行时间对于不同的输入显然也不是一成不变的,排序 1 3 2 显然比排序 1729 237 9123 263 12 123 2813 123 213 123 321 312 3...快得多。
    
    倘若赤裸裸的分析一个算法的话,运行时间指的是算法运行的步数!!!一般呈现这样的关系:运行时间相关于输入规模和输入内容, 
    
    (当然,存在对于特定输入却有不同运行时间的状况,暂且不提)
    
    通常认为,一个算法的增长量级越低就越有效,例如说n^2 相对于 nlogn 显得很笨重!
    
    具体怎么算参考算法导论。
    
     
    
    总之,认识一个算法或者说对待算法的态度应该是:算法有什么用 > 算法效率怎么样 > 算法具体做了什么
    View Code
  • 相关阅读:
    设备像素比devicePixelRatio简单介绍
    详解事件代理委托
    原生dom事件注册和移除事件的封装
    idataway_前端代码规范
    170307、1分钟实现“延迟消息”功能
    170306、wamp中的Apache开启gzip压缩提高网站的响应速度
    170303、PHP微信公众平台开发接口 SDK完整版
    170302、 Apache 使用localhost(127.0.0.1)可以访问,使用本机局域网IP(192.168.2.*)不能访问
    170301、使用Spring AOP实现MySQL数据库读写分离案例分析
    170228、Linux操作系统安装ELK stack日志管理系统--(1)Logstash和Filebeat的安装与使用
  • 原文地址:https://www.cnblogs.com/xkxf/p/7659961.html
Copyright © 2011-2022 走看看