算法时间复杂度+空间复杂度+循环重复创建变量复杂度

⭐前言⭐

本文将要介绍数据结构的开篇–算法的复杂度,包括时间复杂度和空间复杂度。以及我们经常疑惑在循环重复创建变量空间复杂度的分析。
本文将会出现C语言和Java两种语言,以C语言介绍基础,并且用Java来实现。

🎉欢迎关注🔎点赞👍收藏⭐️留言📝
🔑GithubJava仓库,欢迎点击访问🔑
📝博主的笔记链接,第一时间更新📝

复杂度

算法复杂度是指算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。

同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。一个算法的评价主要从时间复杂度和空间复杂度来考虑。

时间复杂度

概念的引出

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。

但是,一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。

但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。

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

下面函数的时间复杂度?

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

我们看见

第一个循环执行了N 2 ^2 2

第二个循环执行了2N次

第三个循环执行10次

所以

F(N)=N 2 ^2 2+2N+10

实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。

当n的值很大时,影响规模的主要是N 2 ^2 2,2N+10的影响微乎其微。

大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

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

而且我们一般关注的是算法的最坏情况
有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

常见时间复杂度

  • 常数阶O(1)
  • 对数阶O(logN)
  • 线性阶O(n)
  • 线性对数阶O(nlogN)
  • 平方阶O(n²)
  • 立方阶O(n³)
  • K次方阶O(n^k)
  • 指数阶(2^n)

实战分析

线性

void func(int n,int m){
    int count=0;
    for(int k=0;k<n;k++){
        count++;
    }
    for(int k=0;k<m;k++){
        count++;
    }
}

第一个循环执行了n次

第二个循环执行了m次

所以时间复杂度为O(M+N)

常数阶

void func(int x){
    for(int i=0;i<100;i++){
        x=i;
    }
}

我们看到循环执行了一百次那么是O(100)?

100次对我们来说还是有限次时间复杂度为O(1)

平方阶

void bubbleSort(int[] array) {
    for (int end = array.length; end > 0; end--) {
        boolean sorted = true;    
        for (int i = 1; i < end; i++) {     
            if (array[i - 1] > array[i]) {          
                Swap(array, i - 1, i);            
                sorted = false;        
            }   
        }            
        if (sorted == true) {        
            break;    
        }
    }
}

这是一个冒泡排序算法的改进型,我们考虑最坏的情况—改进没有用

仍然执行N2

时间复杂度为O(N2)

二分查找对数阶及证明

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

这是一个二分查找,每次砍掉一半,下面我们来对时间复杂度进行证明

一次查找剩下:N/2

二次查找剩下:N/4

m次查找剩下:N/2 m ^m m

很倒霉当m次查找是就剩下一个元素了,执行后无论找没找到都要退出

N/2 m ^m m=1可以得出m= log ⁡ 2 N \log_2{N} log2N

也就是时间复杂度为O( log ⁡ 2 N \log_2{N} log2N)

递归线性

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

计算N需要N-1,计算N-1需要N-2,知道我们需要计算1

时间复杂度为O(N)

指数爆炸

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

看下面这个结构

Snipaste_2021-10-31_20-54-35

我们可以看见呈现指数形式

时间复杂度为O(2 n ^n n)

空间复杂度

概念的引出

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。

空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。

空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。

实战分析

循环重复创建变量

void bubbleSort(int array[]) {
    for (int end = array.length; end > 0; end--) {
        boolean sorted = true;    
        for (int i = 1; i < end; i++) {     
            if (array[i - 1] > array[i]) {          
                Swap(array, i - 1, i);            
                sorted = false;        
            }   
        }            
        if (sorted == true) {        
            break;    
        }
    }
}

运行过程中我们借助了少数常量个空间所以空间复杂度为O(1)

需要注意的是

  1. 传进来一个数组不是我们耗费的空间,我们是对数组进行原地操作
  2. 我们看见有一个布尔类型的变量在重复创建好像创建了N次,但占空间只有一次

解释

函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。时间是累积的,而空间是不累积的(可以重复利用)

递归线性

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的数组

空间复杂度为O(N)

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

递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。

空间复杂度为O(N)

💎结尾语💎

如有错误,欢迎指正

🎉欢迎关注🔎点赞👍收藏⭐️留言📝
🔑GithubJava仓库,欢迎点击访问🔑
📝博主的笔记链接,第一时间更新📝

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
### 回答1: PHP 作为一种编程语言,并没有固定的算法时间复杂度空间复杂度。这些复杂度取决于所编写的算法实现,而不是编程语言本身。 例如,PHP 的排序算法可能具有不同的时间复杂度空间复杂度,如冒泡排序、选择排序、插入排序、快速排序等。具体算法时间复杂度空间复杂度取决于算法的实现方式。 因此,在使用 PHP 进行算法开发时,需要特别注意算法时间复杂度空间复杂度,选择适合自己需求的算法,以获得更好的性能和效率。 ### 回答2: PHP算法时间复杂度是指算法执行所需的时间与问题规模的增长率之间的关系。常见的时间复杂度有常数时间O(1)、对数时间O(log n)、线性时间O(n)、平方时间O(n^2)等。在PHP,根据具体的算法实现方式,时间复杂度可以不同。 在PHP,一般来说,使用循环算法通常会有较高的时间复杂度。例如,一个遍历数组并求和的算法,其时间复杂度为O(n),其n是数组的长度。另外,PHP还提供了一些内置函数和数据结构,如排序函数sort()和二分查找函数array_search()等,它们的时间复杂度通常是比较高效的。 PHP算法空间复杂度是指算法所需的额外空间与问题规模的增长率之间的关系。常见的空间复杂度有常数空间O(1)、线性空间O(n)、平方空间O(n^2)等。在PHP空间复杂度通常是由变量、数组和函数调用所需的额外空间来衡量的。 在PHP空间复杂度较高的算法通常是由于需要创建额外的数据结构临时变量来存储间结果。例如,一个需要创建一个与输入规模n相关的数组来存储计算结果的算法,其空间复杂度为O(n)。 综上所述,PHP算法时间复杂度空间复杂度可以根据具体的算法实现方式而有所不同,但通常可以通过分析循环次数、临时变量的数量和额外数据结构的大小来进行评估和比较。在编写PHP算法时,我们应该尽量选择高效的时间复杂度和较低的空间复杂度,以提高算法的性能和效率。 ### 回答3: PHP算法时间复杂度空间复杂度取决于具体使用的算法数据结构时间复杂度是用来表示算法执行所需时间的度量,通常以大O表示。在PHP,常见的时间复杂度包括O(1)、O(log n)、O(n)、O(n log n)和O(n^2)等。具体的算法实现会决定时间复杂度的大小。 空间复杂度是用来表示算法在执行过程所需的额外空间的度量,也通常以大O表示。在PHP,常见的空间复杂度包括O(1)、O(n)、O(n^2)等。具体的算法实现决定了空间复杂度的大小。 例如,对于PHP的数组排序算法,使用快速排序算法时间复杂度为O(n log n),空间复杂度为O(log n)。这是因为快速排序算法的平均时间复杂度为O(n log n),但需要额外的递归调用栈空间。另外,对于PHP的线性查找算法时间复杂度为O(n),空间复杂度为O(1),这是因为在执行过程不需要额外的空间存储数据。 总而言之,PHP算法时间复杂度空间复杂度是评估算法性能和资源消耗的重要指标,具体取决于所使用的算法数据结构
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海是冰川蓝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值