一个算法对于某个输入的循环次数是可以事先估计出来的_算法的基础知识

fe023931ea56fa0dbb8dacb586803610.png

1. 什么是算法

1.1 直观理解

算法就是告诉计算机怎么做,计算机是不会独立思考的,我们必须提供详尽的指令,使用它们能够理解的语言将步骤提供给他们。算法详尽描述了如何完成某项任务,就像菜谱那样详细描述了如何做出一道菜。

1.2 官方定义

算法的有穷性:

在有限的操作步骤内完成,否则计算机会一直执行到资源耗尽后死机。

算法的确定性:

每个步骤明确,步骤的结果确定。算法执行的过程是与计算机交互的过程,每一步必须明确而且具有符合语言规则,否则计算机无法执行,会报错。

算法的可行性:

每个步骤有效执行,得到确定的结果。每一个具体步骤中通过计算机实现时应能够使计算机完成,如果这一步骤计算机无法实现,也就达不到预期的目的,那么这一步骤是不完善和不明确的,是不可行的。

零个或多个输入:

从外界获取信息,可以没有输入,也可以有多种类型的多个输入,需要根据具体问题具体分析。

一个或者多个输出:

算法得到的结果就是算法的输出。算法的目的是为了解决一个具体问题,一旦问题解决了,就说明采取的算法书正确的,而结果的输出正是验证这一目的的最好方式。

2. 如何选择算法

当多个算法都可以解决同一个问题的时候,我们应该如何选择呢?在算法的评判上,考量的标准也各不相同,一个算法的质量优劣将影响到程序的效率。时间和空间都是计算机资源的重要体现,而算法的复杂性就是体现在运行该算法时的计算机所需的资源多少。

比如,简单的算法对人来说易于理解,也容易被编写成程序,而在运行的时候不需要耗费太多空间资源的算法,就十分适合内存小的计算机。

不过,一般来说,最为重视的是算法的运行时间,即从输入到输出这个过程所花费的时间。

3. 算法的复杂度

算法的复杂度分为时间复杂度和空间复杂度。时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。

3.1 时间复杂度

一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n);

n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。记为O(…),也称为大O表示法;

3.2 空间复杂度

一个程序的空间复杂度是指运行完一个程序所需要的内存大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。

  • 固定部分:这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
  • 可变空间:这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。

4. 如何计算时间复杂度

4.1 遵循如下规则

  • 用常数1来取代运行时间中所有加法常数;
  • 只要高阶项,不要低阶项;
  • 不要高阶项系数;

4.2 常见的时间复杂度

  • O(1)—常数阶:运算次数是常数
temp

根据规则1:用常数1来取代运行时间中所有加法常数;

上面语句共三条操作,单条操作的频度为1,即使他有成千上万条操作,也只是个较大常数,这一类的时间复杂度为O(1);

  • O(N)—线性阶
sum=0;                 
for(i=0;i<n;i++)       
    sum++;

根据规则:只要高阶项,不要低阶项目,常数项置为1,去除高阶项的系数:

所以时间复杂度O(n)。这一类算法中操作次数和n正比线性增长。

  • O(log2N)—对数阶
    private static void 对数阶() {
        int number = 1;//执行1次
        int n = 100;//执行1次

        while (number < n) {
            number = number * 2; // 执行n/2次
            System.out.println("哈哈");//执行1次
        }

    }

n为100,number是1,小于100退出循环。

第1次循环,number = 2,2^1。

第2次循环,number = 4, 2^2。

第3次循环,number = 8, 2^3。

第x次循环,number = 2^x

也就是2^x=n得出x=log₂n。因此它的复杂度为O(logn)。

  • O(nlogn)—线性对数阶

线性对数阶就是在LogN的基础上多了一个线性阶;

比如这么一个算法流程:数组a和b,a的规模为n,遍历的同时对b进行二分查找,如下代码:

for(int i =0;i<n;i++)
    binary_search(b);
}
  • O(n^2)—平方阶

平方阶就是嵌套循环

    private static void 普通平方阶(){
        int n = 100;
        for (int i = 0; i < n; i++) {//执行n次
            for (int j = 0; j < n; j++) {//执行n次
                System.out.println("哈哈");
            }
        }
    }

4.3 粗略计算时间复杂度的三部曲

1.去掉运行时间中的所有加法常数。

没有加法常数,不考虑。

2.只保留最高阶项。

最高阶参考上面列出的按增长量级递增排列,于是只需要保留result = (n^2)/2

3.如果最高阶项存在且不是1,去掉与这个最高阶相乘的常数得到时间复杂度

除以2相当于是乘以二分之一,去掉它,就得到,result = n^2, 所以这个算法的时间复杂度为O(n^2)。

4.4 时间复杂度优劣对比

常见的数量级大小:越小表示算法的执行时间频度越短,则越优;

O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值