算法--时间复杂度与空间复杂度

简介: 算法--时间复杂度与空间复杂度

时间和空间复杂度

[TOC]

首先要知道为什么要有时间和空间复杂度的概念,要想知道一个程序的执行效率理论上来说就应该直接上机测试,但是由于硬件的差异,我们很难做到统一,所以就产生了时间和空间复杂度,用来估计算法的效率。

时间复杂度

时间复杂度主要衡量的是一个算法的运行速度

时间复杂度的概念

时间复杂度的定义:一个算法所花费的时间与其中语句的执行次数成正比例,==算法中的基本操作的执行次数,为算法的时间复杂度==

时间复杂度有最好情况下,平均情况下和最坏情况下

一般指的时间复杂度是最坏情况下

大O渐进表示法

我们只需要将知道一个大概的执行次数就可以了,所以采用大O渐进表示法

image-20220416213917965

// 请计算一下func1基本操作执行了多少次?
void func1(int N){
int count = 0;
for (int i = 0; i < 2N ; i++) {
    for (int j = 0; j < N^2 ; j++) {
    count++;
    }
}
for (int k = 0; k < 2 * N ; k++) {
    count++;
}
int M = 10;
while ((M--) > 0) {
    count++;
}

精确计算就是2 N^3+2*N+10,但是经过大O渐进表示法,就是时间复杂度就是O(N ^3)

几个例子

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);
}

2* N+10,去掉后面的数字,去掉系数,所以时间复杂度就是O(N)

// 计算func3的时间复杂度?
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);
}

由于M和N未知,所以就是O(M+N)

void func4(int N) {
int count = 0;
for (int k = 0; k < 100; k++) {
    count++;
}
System.out.println(count);
}    

循环了100次,是一个确定的常数,所以就是O(1)

image-20220416225158881

最坏情况下就是不优化,N*(N-1)=N^2-N,所以时间复杂度(最坏情况)就是O(N ^2 )

最好的情况就是数组就是升序的,只走了一遍全部数字,第二个循环就直接跳出去了,没有发生交换,所以此时 最好的情况就是O(N)

冒泡排序完整版(升序)

import java.util.Arrays;

 class BubbleSort {
  public  static void  bubblesort(int[] arr) {      //记得加上static,确保main里面可以带调用
        for (int end =arr.length;end>0;end--) {
            boolean flag=true;
            for (int i = 1; i <end ; i++) {
                if (arr[i - 1] > arr[i]) {
                    int tmp = arr[i - 1];
                    arr[i - 1] = arr[i];
                    arr[i] = tmp;
                }
                flag = false;
            }
            if (flag==true) {
                break;
            }
        }
    }
    public static void main(String[] args) {
        int[] arr = {1, 3, 2, 4, 23, 6};
        //BubbleSort bubbleSort = new BubbleSort();
        //要是上面的方法没有加上static也可以定义一个对象,new一下直接补全
        //但还是在方法前面加上static最省心
        bubblesort(arr);
        System.out.println(Arrays.toString(arr));

    }
}

冒泡排序+二分查找

import java.util.Arrays;
import java.util.Scanner;

//冒泡排序
public class BubbleSort {
    static void  bubblesort(int[] arr) {
        for (int end =arr.length;end>0;end--) {
            boolean flag=false;
            for (int i = 1; i <end ; i++) {
                if (arr[i - 1] > arr[i]) {
                    int tmp = arr[i - 1];
                    arr[i - 1] = arr[i];
                    arr[i] = tmp;
                }
                flag = true;
            }
            if (!flag) {
                break;
            }
        }
    }
//二分查找
    static int  Binarysort(int[] arr, int value) {
        int l=0;
        int r=arr.length-1;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if (arr[mid] < value) {
                l = mid + 1;
            } else if (arr[mid] > value) {
                r = mid - 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
    
    public static void main(String[] args) {
        int[] arr = {1, 3, 2, 4, 23, 6};
        bubblesort(arr);//二分查找的前提是有序数组
        Scanner scanner = new Scanner(System.in);//创建一个scanner的对象
        while (scanner.hasNext()) {
            int value = scanner.nextInt();
            if (Binarysort(arr, value) == -1) {
                System.out.println("找不到这个数字");
            }else{
                System.out.println("找到了,下标为"+Binarysort(arr, value));
            }
        }
    }

二分查找的时间复杂度

最坏的情况就是要找的数字在最右边,此时要查找的次数最多

image-20220429220443110

image-20220630134437672

所以二分查找的时间复杂度是O(log2n)

递归的时间复杂度

递归的时间复杂度=递归的次数*每次递归执行的次数

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

public static int factorial(int n) {
    return n > 2 ? n : factorial(n - 1) * n;
}

一共要递归n-1次,每次递归执行一次三目运算符,所以这个阶乘的时间复杂度是O(n)

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

public static int feb(int n) {
        return n < 2 ? n : feb(n - 1) + feb(n - 2);
    }

image-20220429223018424

假设n=3,要是在最坏情况下,那就是2^ 0+2^ 1+2^ 2

类比开来,就是2^0+2^ 0+2^ 1+2^ 2 +……+2^(n-1) ,也就是一个等比数列求和问题

所以结果为2^n+1,所以时间复杂度为O(2 ^n) ---指数级别增长

空间复杂度

==空间复杂度算的是额外的变量的个数。==空间复杂度也使用大O渐进表示法。

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


public class BubbleSort {
    static void  bubblesort(int[] arr) {
        for (int end =arr.length;end>0;end--) {
            boolean flag=false;
            for (int i = 1; i <end ; i++) {
                if (arr[i - 1] > arr[i]) {
                    int tmp = arr[i - 1];
                    arr[i - 1] = arr[i];
                    arr[i] = tmp;
                }
                flag = true;
            }
            if (!flag) {
                break;
            }
        }
    }

在代码运行的时候,有end、flg、i 、tmp 4个额外的变量,所以空间复杂度是O(1)

计算斐波那契数的空间复杂度


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+1,s所以时间复杂度是O(N)

递归的空间复杂度

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

每递归进去一次,就要开辟一次内存,所以这个阶乘的空间复杂度是O(N)

常见的时间复杂度:O(1)、O(log2n)、O(N)、O(N*log2n>)、O(N^2)、O(2 ^n)

以上的时间复杂度的效率是越来越慢的

总结来说,要想知道时间复杂度不能只看代码,还要关注代码的实现思想。

目录
相关文章
|
27天前
|
机器学习/深度学习 缓存 算法
Python算法设计中的时间复杂度与空间复杂度,你真的理解对了吗?
【10月更文挑战第4天】在Python编程中,算法的设计与优化至关重要,尤其在数据处理、科学计算及机器学习领域。本文探讨了评估算法性能的核心指标——时间复杂度和空间复杂度。通过详细解释两者的概念,并提供快速排序和字符串反转的示例代码,帮助读者深入理解这些概念。同时,文章还讨论了如何在实际应用中平衡时间和空间复杂度,以实现最优性能。
56 6
|
3月前
|
机器学习/深度学习 算法 程序员
读《趣学算法》:重开算法之门,时间复杂度与空间复杂度
本文是作者阅读《趣学算法》后的笔记,介绍了算法复杂度的基本概念,包括时间复杂度和空间复杂度的不同阶表示,并通过具体例子展示了如何计算和理解算法的效率。
64 2
读《趣学算法》:重开算法之门,时间复杂度与空间复杂度
|
19天前
|
搜索推荐 算法
插入排序算法的平均时间复杂度解析
【10月更文挑战第12天】 插入排序是一种简单直观的排序算法,通过不断将未排序元素插入到已排序部分的合适位置来完成排序。其平均时间复杂度为$O(n^2)$,适用于小规模或部分有序的数据。尽管效率不高,但在特定场景下仍具优势。
|
25天前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
19 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
1月前
|
存储 算法
算法的时间复杂度和空间复杂度
本文详细讨论了算法的时间复杂度和空间复杂度,包括它们的概念、计算方法和常见复杂度的对比,并通过多个实例解释了如何计算算法的时间和空间复杂度。
42 0
算法的时间复杂度和空间复杂度
|
1月前
|
机器学习/深度学习 存储 算法
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
|
2月前
|
算法 Python
震惊!Python 算法设计背后,时间复杂度与空间复杂度的惊天秘密大起底!
在 Python 算法设计中,理解并巧妙运用时间复杂度和空间复杂度的知识,是实现高效、优雅代码的必经之路。通过不断地实践和优化,我们能够在这两个因素之间找到最佳的平衡点,创造出性能卓越的程序。
39 4
|
2月前
|
缓存 算法 数据处理
时间&空间复杂度,Python 算法的双重考验!如何优雅地平衡两者,打造极致性能?
在Python算法中,时间与空间复杂度的平衡至关重要。时间复杂度反映算法执行时间随输入规模的变化趋势,空间复杂度则关注额外存储空间的需求。优秀的算法需兼顾两者,如线性搜索时间复杂度为O(n),空间复杂度为O(1);二分查找在时间效率上显著提升至O(log n),空间复杂度保持为O(1);动态规划通过牺牲O(n)空间换取O(n)时间内的高效计算。实际应用中,需根据具体需求权衡,如实时数据处理重视时间效率,而嵌入式系统更关注空间节约。通过不断优化,我们能在Python中找到最佳平衡点,实现高性能程序。
63 3
|
1月前
|
算法 C语言
深入理解算法效率:时间复杂度与空间复杂度
深入理解算法效率:时间复杂度与空间复杂度
|
12天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。