算法第四版学习(chapter1.4)part1

    马上开始今天的学习,今天的内容是算法分析,算法的一个评估环节,当我们在设计、使用一个算法的时候,一个算法的好坏往往与它的运行时间(时间复杂度),运行所需空间(空间复杂度)挂钩,首先来学习时间复杂度问题。

     书中一开始提到一个例子,讲的是计算从数组中抽取三个数,统计三个数加起来等于0的个例,然后进行返回。文章之中给出的ThreeSum,典型的暴力算法,逐个遍历,在P112,我遇到了我第一个问题,if语句会执行N(N-1)(N-2)/6次,这个6是哪里来的呢,下面我们就来分析一下,其实if语句的执行次数就是这三个嵌套循环的核心循环的执行次数,三个循环分别是为了找出第一个数,第二个数和第三个数,若果是N(N-1)(N-2),这就是表明了,每个数字的位置是没什么要求的,只要跟上一个不重就好了,就像从箱子里抽球,抽一个,总数减一个,抽一个,总数再减一,那我们可能会抽到1  2  5, 5  2  1,在这个问题里这两个 抽取有差吗?其实并不是这样的,我们只是要三个,先后次序并没用,运用数学排列组合公式。

        {C} _{all}^{3}=(all)(all-1)(all-2)/3*2*1             {A} _{all}^{3}=(all)(all-1)(all-2)    

我们能清晰地看出无序选择在这个问题中是有选择的1/6的规模,好吧1/6得出来了。

知识点一:当N足够大的时候,我们将我们往往只要考虑次方最高的的式子就好了,例如书上的1/6N^{3}-1/2N^{2}+1/3N^{1},当N足够大的时候,次方小的完全可以忽略不计。

知识点二:数量级,①取最大次方 ②没有次方的话,有对数就是对数级别或者线性对数级别(单个变量跟对数相乘) ③对数都没有的话,有单个变量的叫做线性④变量都没有的话就是常数次了。

知识点三:常用算法的数量级,普通语句,最普通的语句,常数级别;二分查找,对数级别;归并排序线性对数级别;嵌套循环,多少层嵌套就多少次方级别;穷举,指数级别。

     话不多说,我们来改造一下那个丢人的ThreeSum算法吧,书中将第三层循环去掉,套了一个二分查找,将N^3降为了N^2logN。

倍率实验:通过提高实验的基数,测试执行时间之间的倍率,书上给的例子,由于数量级为N^3,在实验基数*2的情况下,时间倍率慢慢稳定在8,2^3=8嘛,比如2^3/1^3=8,4^3/2^3=8.

书上讲到一个~,近似,类似于高数上极限的问题,当n足够大的时候,使得F(x)近似等于G(x),是由于分母太大啊,或者对数底数太大啊,而造成的,接近于0嘛

评估一个算法的注意事项

    ①虽然跟次方数比起来,常数有点微不足道,但是其实有些时候,会有一些大常数的出现,比如它就执行1000次,虽然当N很大的时候吗,它微不足道,但是当N小的时候,N的次方或许还没有它大呢。

   ②非决定性的内循环,就是这种内循环并不是执行算法的关键操作,而在外部有更多指令需要消耗大量的时间,这样的话,我们在计算整体的时间数量级的时候,我们就不能只是考虑内循环。

   ③有的时候,算法在执行的过程中并没有达到设想的效率,可能是因为计算机的机制问题,比如java来说,你一下子创建太多的对象,又一下子释放,垃圾回收机制在没进行回收之前,会一定程度的影响到运行的速度。

   均摊分析:有时候我们在分析一些算法的时候,他们会在某个时候,突然出现耗时很高的操作,这些操作可能是为了,之后的算法能够平均上减少算法的耗时。

内存:

    我们在设计算法的时候,不应只考虑时间复杂度,还应该考虑到空间复杂度(尽管如今的计算机,运算空间都是充裕的),书上分别讲述了各种数据结构在java上所占内存大小,需要记忆一些重要地。

如:基本数据类型所占的内存大小:boolean 1个字节 byte 1个字节 char 2个字节 int 4个字节 float 4个字节 long 8个字节 double 8个字节,而组装成对象的话,就这么算吧,对象开销16字节(用来放引用,垃圾收集信息,同步信息),然后基本类型有多少个市设恩么就占多少位置,引用外部对象就要8个字节,最后取8的整数倍,多余的叫做填充字节。不同种类的数据类型有不同的组成部分。

练习部分:(以后的话我会选择,比较有难度的题去做,看一眼就有思路的或者测试工具包的,我可能会选择跳过)

1.4.1 前面分析过了

1.4.2 较大int溢出问题;在处理int之前:用int最大值-其中一个,在跟另一个作比较,如果另一个要更大,就肯定会产生溢出,就跳过。

1.4.3 打印标准图像和对数图像:这个嘛,标准的话最简单了,y=kx+b嘛,输入k和b之后,从x=0,y=b开始,按着你想要的密度画就好了,不如点与点之间x的间隔为0.1,循环时x+0.1,y+k(0.1x),循环直到结束,而对数的话,我们可以一选择用java自带的Math算出对数值,再画点。

1.4.4 最后结果的数量级 N^2,表格主要用来分析,循环过程中每一层循环的执行次数,相加之后去近似数,得到数量级

1.4.5 这种基础性问题我就略过了,以后就直接题号都不写了。

1.4.6 求增长数量级

    先说a,第一层循环for(int n=N;n>0;n/=2),一看到/2,对数好吧,log2N,再看第二层内有乾坤,是每次n的大小,但是n每次减半,所以二层应该是n+n/2+n/4+....+n/N+0,所以第二层的数量级为2n->n,所以整体的数量级应为n

   b呢,只是第一层遍历反过来而已,最后是一样的,数量级是n

   c呢,一层同样log2N,第二层N,相乘得Nlog2N

1.4.8 这个问题我感觉有点问题,在使用了Arraysort之后,已经基本有序了,我只要遍历一次就好了呀,说下我的想法哈,int p=a[0],int num=0,sum=0开始遍历,若跟p相同,num+1,知道遇到跟p不一样的,若num>1,将num排列组合{C}_{2}^{num},sum+结果,

p=新的a[i],继续往后遍历,知道遍历完成,得到sum,这个计算公司的操作顶多算个数量级1,整体数量级N+1,即N

1.4.9 计算题,没什么好讲的

1.4.10 二分的改进要求输出序号最小的与键值相等的位置。

public class BinarySearchLeft {
    int[] a={1,2,3,4,5,5,6,7,8,10};
    public static void main(String[] args) {

        BinarySearchLeft bsl=new BinarySearchLeft();
        //搜索5,按照题意应该返回的是4,下面来讲一下,我所选择的方法,正常的话,当a[mid]==key;
        //是直接返回mid的,我就修改一点点,当a[mid]==key的时候,继续跑二分,r=mid,
        //if(a[mid]==key),而且r==l,输出mid,跳出方法
        //但是我们还需要考虑一个问题,就是数组里面根本没有这个数字
        //当没有的话l会大于r,跳出循环,输出底下那句话
        //跟你们讲下过程,用我上面的数组,一开始mid为5,a[5]正好是key值,命中r=mid,考虑部分缩成
        //1 2 3 4 5 5,mid=2,a[2]<5,l=mid+1=3,考虑部分缩成4 5 5,a[mid]命中,变成 4 5,a[mid]<5,
        //l=mid+1;l=4,r=4,a[mid]=key,输出结果结束
        bsl.bs(0,10,5);
    }

    public void bs(int left,int right,int key){
        int l=left;
        int r=right;
        int mid=0;
        while(!(l>r)){
            mid=(l+r)/2;
            if(a[mid]>key){
                r=mid-1;
            }else if(a[mid]<key){
                l=mid+1;
            }else {
                if (l==r) {
                    System.out.println(mid);
                    return;
                }
                r=mid;
            }
        }
        System.out.println("数字不存在");
    }
}

1.4.12 两个有序数组分开放置在两个队列里,队头进行比较,小的出队,当其中一个队列全部出列,另一队列也全部出列,数量级也就N,因为完成4最快是N,最慢的话是2N-1

1.4.13 计算对象所占内存,

第一个Accumulator,首先创建对象要16个字节,然后对象内部有一个double占8个字节,好吧24个字节。

第二个Transaction,唉呀!找不到,好奇啊,反正也就那样组装,不写了。

提高题之后再补充,今天就这样吧,算法的分析,这里好像并没非常量化的衡量算法复杂度,只是一个粗略的分析,真正的算法分析是不会考虑到任何除算法以外的条件的,计算机运行速度啊,时钟周期,都不在考虑范围之内。

发布了8 篇原创文章 · 获赞 2 · 访问量 1626

猜你喜欢

转载自blog.csdn.net/z1261203654/article/details/81913079