服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java 数据结构之时间复杂度与空间复杂度详解

Java 数据结构之时间复杂度与空间复杂度详解

2022-07-08 10:04Lockey-s Java教程

算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是度量算法执行的时间长短;而空间复杂度是度量算法所需存储空间的大小

算法效率

在使用当中,算法效率分为两种,一是时间效率(时间复杂度),二是空间效率(空间复杂度)。时间复杂度是指程序运行的速度。空间复杂度是指一个算法所需要的额外的空间。

时间复杂度

什么是时间复杂度

计算程序运行的时间不能拿简单的时间来计算,因为不同处理器处理数据的能力是不一样的。所以只算一个大概的次数就行了,俨然就是算法中的基本操作的执行次数。用大o的渐进法来表示

例:计算 func1 的基本操作执行了几次

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void func1(int n){
    int count = 0;
    for (int i = 0; i < n ; i++) {
        for (int j = 0; j < n ; j++) {
            count++;
        }
    }
    for (int k = 0; k < 2 * n ; k++) {
        count++;
    }
    int m = 10;
    while ((m--) > 0) {
        count++;
    }
    system.out.println(count);
}

func1 的基本执行次数是:f(n) = n^2 + 2*n + 10

推导大 o 阶的方法

1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大o阶。

所以使用大 o 的渐进法表示之后,func1 的时间复杂度就是:o(n^2)

算法情况

因为当我们用算法计算的时候,会有最好情况和最坏情况和平均情况。我们常说的时间复杂度在 o(n) 这里的时间复杂度就是最坏情况。
最好情况就是最小的运行次数。

举例一:

?
1
2
3
4
5
6
7
8
9
10
11
void func2(int n){
    int count = 0;
    for (int k = 0; k < 2 * n ; k++) {
        count++;
    }
    int m = 10;
    while ((m--) > 0) {
        count++;
    }
    system.out.println(count);
}

这里的结果是 o(n) 因为根据时间复杂度的计算方法,去除常数,所以 2*n 就是 n 。m 是 10 也可以忽略掉。

举例二:

?
1
2
3
4
5
6
7
8
9
10
void func3(int n, int m) {
    int count = 0;
    for (int k = 0; k < m; k++) {
        count++;
    }
    for (int k = 0; k < n ; k++) {
        count++;
    }
    system.out.println(count);
}

这里的时间复杂度是 o(m+n) 因为 m 和 n 的值是未知的,所以是 o(m+n)

举例三:

?
1
2
3
4
5
6
7
void func4(int n) {
    int count = 0;
    for (int k = 0; k < 100; k++) {
        count++;
    }
    system.out.println(count);
}

这个的时间复杂度是 o(1) 因为循环里面是常数,所以根据大 o 渐进法,结果就是 o(1)

计算冒泡排序的时间复杂度

?
1
2
3
4
5
6
7
8
9
10
11
public static void bubblesort(int[] arr){
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if(arr[j] > arr[j+1]){
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
}

因为冒泡排序的特殊性,可能一次就排好了,也可能得一直排到最后,所以就有了最好情况和最坏情况。

最好情况:就是比较一次,就是 o(n)
最坏情况:一直排到最后,就是 o(n^2)

计算二分查找的时间复杂度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int binarysearch(int[] array, int value) {
    int begin = 0;
    int end = array.length - 1;
    while (begin <= end) {
        int mid = begin + ((end-begin) / 2);
        if (array[mid] < value)
            begin = mid + 1;
        else if (array[mid] > value)
            end = mid - 1;
        else
            return mid;
    }
    return -1;
}

因为二分查找是一半一半的找,所以每次查找之后都会把查找范围减半,比如说在一个 1 - 8 的有序数组里面查找 8 也就是查找最坏情况。图示如下:

Java 数据结构之时间复杂度与空间复杂度详解

如图,在数组当中完成二分查找需要 log2n - 1 次也就是时间复杂度是 log2n (就是 log 以 2 为底 n 的对数)

计算阶乘递归的时间复杂度

?
1
2
3
long factorial(int n) {
    return n < 2 ? n : factorial(n-1) * n;
}

计算递归的时间复杂度:递归的次数 * 每次递归执行的次数。

所以这次递归的时候,基本操作递归了 n 次,所以时间复杂度就是 o(n)

计算斐波那契递归的时间复杂度

?
1
2
3
int fibonacci(int n) {
    return n < 2 ? n : fibonacci(n-1)+fibonacci(n-2);
}

假设 n 是 5 我们来展开求

Java 数据结构之时间复杂度与空间复杂度详解

如图:每次计算都会计算下一层,但是每次都是一边少,一边多。所以就可以直接按照每边一样来计算。如下图:

Java 数据结构之时间复杂度与空间复杂度详解

所以就有公式可以计算出每次计算的次数,就是:2 ^ (n - 1) ,所以计算的结果就是:2^\0 + 2^1 + 2^2 + 2^3……2^(n-1) = 2^n+1 所以按照大 o 渐进法来算,结果就是:2^n 。

所以斐波那契数列的时间复杂度就是:2^n 。

空间复杂度

空间复杂度衡量的是一个算法在运行过程当中占用的额外存储空间的大小,因为没必要按照字节来算,而是算变量的个数。也是用大 o 渐进法表示。

计算冒泡排序的空间复杂度

?
1
2
3
4
5
6
7
8
9
10
11
public static void bubblesort(int[] arr){
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if(arr[j] > arr[j+1]){
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
}

因为冒泡排序的变量并没有变化,使用的是额外空间是常数,所以空间复杂度是 o(1) 。

计算斐波那契数列的空间复杂度(非递归)

?
1
2
3
4
5
6
7
8
9
int[] fibonacci(int n) {
    long[] fibarray = new long[n + 1];
    fibarray[0] = 0;
    fibarray[1] = 1;
    for (int i = 2; i <= n ; i++) {
        fibarray[i] = fibarray[i - 1] + fibarray [i - 2];
    }
    return fibarray;
}

因为这里的斐波那契数列开辟了 n 个额外空间,所以空间复杂度为 o(n) 。

计算阶乘递归factorial的时间复杂度

?
1
2
3
int factorial(int n) {
    return n < 2 ? n : factorial(n-1)*n;
}

因为是递归,每次递归都会开辟栈帧,每个栈帧占用常数个空间,所以空间复杂度就是 o(n) 。

到此这篇关于java 数据结构之时间复杂度与空间复杂度详解的文章就介绍到这了,更多相关java 数据结构内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/sjp151/article/details/121125585

延伸 · 阅读

精彩推荐
  • Java教程java实现倾斜水印铺满整张图

    java实现倾斜水印铺满整张图

    这篇文章主要为大家详细介绍了java实现倾斜水印铺满整张图的具体代码,教大家如何控制水印之间的空隙,感兴趣的小伙伴们可以参考一下 ...

    Mr_Smile20148592020-05-21
  • Java教程详解Spring Boot 事务的使用

    详解Spring Boot 事务的使用

    spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。接下来通...

    Java教程网5442020-09-08
  • Java教程Java中典型的内存泄露问题和解决方法

    Java中典型的内存泄露问题和解决方法

    这篇文章主要介绍了Java中典型的内存泄露问题和解决方法,典型的内存泄露例子是一个没有实现hasCode和 equals方法的Key类在HashMap中保存的情况,可以通过实...

    Java教程网3052019-11-21
  • Java教程Spring框架开发IOC两种创建工厂方法详解

    Spring框架开发IOC两种创建工厂方法详解

    这篇文章主要介绍了Spring框架IOC两种创建工厂方法详解,文中附含详细的代码示例分别对静态方法和实例方法创建工厂作了简要的分析...

    DrLai12422022-01-05
  • Java教程Java实现两人五子棋游戏(三) 画出棋子

    Java实现两人五子棋游戏(三) 画出棋子

    这篇文章主要为大家详细介绍了Java实现两人五子棋游戏,画出五子棋的棋子,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    v_xchen_v8602021-04-15
  • Java教程详解Spring学习之编程式事务管理

    详解Spring学习之编程式事务管理

    本篇文章主要介绍了详解Spring学习之编程式事务管理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    颜洛滨3852020-12-03
  • Java教程Java中的字符串用法小结

    Java中的字符串用法小结

    这篇文章主要介绍了Java中的字符串用法,实例总结了java中关于字符串操作的各种常用的技巧,非常具有实用价值,需要的朋友可以参考下 ...

    司青2532019-12-16
  • Java教程java Date获取年月日时分秒的实现方法

    java Date获取年月日时分秒的实现方法

    下面小编就为大家带来一篇java Date获取年月日时分秒的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    java教程网5352020-05-19