5分钟带你快速认识时间复杂度与空间复杂度

本文详细探讨了时间复杂度和空间复杂度在算法分析中的重要性,通过求和案例对比了不同代码执行速度,介绍了大O记法,并强调了在选择算法时对时间和空间复杂度的考量。此外,文章还提到了空间复杂度在早期编程中的关注点,以及现代环境下对内存占用的简化处理。
摘要由CSDN通过智能技术生成

数据结构与算法

一 时间复杂度与空间复杂度

有关算法时间耗费分析,我们称之为算法的时 间复杂度分析,有关算法的空间耗费分析,我们称之为算法的空间复杂度分析。

1.1 时间复杂度(重点)

取决因素

  • 代码质量
  • 执行机器的优劣,执行指令的速度
  • 算法采用的策略和
  • 问题的输入规模
  • 。。。。。。

案例:求和1-100的和?

package 算法入门.求和;

/**
 * @author shu
 * @date 2021/6/7
 * @description 普通求和
 */
public class SumText01 {
    public static void main(String[] args) {
        int sum = 0;
        int n=100;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        System.out.println("sum=" + sum);
    }
}
package 算法入门.求和;

/**
 * @author shu
 * @date 2021/6/7
 * @description 高斯算法 an=(an+a1)n/2
 */
public class SumText02 {
    public static void main(String[] args) {
            int sum = 0;
            int n=100;
            sum = (n+1)*n/2;
            System.out.println("sum="+sum);
    }
}

你认为上面两种解法?谁的速度更快?

1.2 分析

如果输入量为n为1,则需要计算1次;
如果输入量n为1亿,则需要计算1亿次;
public static void main(String[] args) {
int sum = 0;//执行1次
int n=100;//执行1次
for (int i = 1; i <= n; i++) {//执行了n+1次
sum += i;//执行了n次
}
System.out.println("sum=" + sum);
}
//时间复杂度O(1)
如果输入量为n为1,则需要计算1次;
如果输入量n为1亿,则需要计算1次;
public static void main(String[] args) {
int sum = 0;//执行1次
int n=100;//执行1次
sum = (n+1)*n/2;//执行1次
System.out.println("sum="+sum);
}
//时间复杂度O(n)
  • 我们研究算法复杂度,侧重的是当输入规模不断增大时,算法的增长量的一个抽象(规律),而不是精确地定位需要 执行多少次,因为如果是这样的话,我们又得考虑回编译期优化等问题,容易主次跌倒,我们分析一个算法的运行时间,最重要的 就是把核心操作的次数和输入规模关联起来。
  • 别急,我们慢慢来看一下,怎样计算出时间复杂度的?

1.3 测试

  • 常数影响
    在这里插入图片描述

上图可以看出常数对其影响还行很小的

  • 输入规模影响

在这里插入图片描述

上图可以看出输入规模对其影响还行很小的

  • 指数的影响

在这里插入图片描述

最高次项的指数大的,随着n的增长,结果也会变得增长特别快

总结

  • 算法函数中的常数可以忽略
  • 算法函数中最高次幂的常数因子可以忽略
  • 算法函数中最高次幂越小,算法效率越高

1.4 大O记法(也适用于函数调用)

  • 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随着n的变化情况并确定T(n)的 量级。算法的时间复杂度,就是算法的时间量度,记作:T(n)=O(f(n))。
  • 它表示随着问题规模n的增大,算法执行时间 的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称时间复杂度,其中f(n)是问题规模n的某个函数。
  • 在这里,我们需要明确一个事情:执行次数=执行时间 用大写O()来体现算法时间复杂度的记法,我们称之为大O记法。

规则

  • 用常数1取代运行时间中的所有加法常数
  • 在修改后的运行次数中,只保留高阶项
  • 如果最高阶项存在,且常数因子不为1,则去除与这个项相乘的常数

案例

public static void main(String[] args) {
int sum = 0;//执行1次
int n=100;//执行1次
sum = (n+1)*n/2;//执行1次
System.out.println("sum="+sum);
}
//时间复杂度:3次 O(1)
public static void main(String[] args) {
int sum = 0;//执行1次
int n=100;//执行1次
for (int i = 1; i <= n; i++) {
sum += i;//执行了n次
}
System.out.println("sum=" + sum);
}
//时间复杂度 n+3次  O(n)
public static void main(String[] args) {
int sum=0;//执行1次
int n=100;//执行1次
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=n ; j++) {
sum+=i;//执行n^2次
}
}
System.out.println("sum="+sum);
}
//时间复杂度 n^2+2次 O(n^2)

1.5 注意

在这里插入图片描述

  • 我们会发现,从平方阶开始,随着输入规模的增大,时间成本会急剧增大,所以,我们的 算法,尽可能的追求的是O(1),O(logn),O(n),O(nlogn)这几种时间复杂度,而如果发现算法的时间复杂度为平方阶、 立方阶或者更复杂的,那我们可以分为这种算法是不可取的,需要优化。

1.6 空间复杂度(了解)

计算机的软硬件都经历了一个比较漫长的演变史,作为为运算提供环境的内存,更是如此,从早些时候的512k,经 历了1M,2M,4M...等,发展到现在的8G,甚至16G32G,所以早期,算法在运行过程中对内存的占用情况也是 一个经常需要考虑的问题。我么可以用算法的空间复杂度来描述算法对内存的占用。
在这里插入图片描述

算法的空间复杂度计算公式记作:S(n)=O(f(n)),其中n为输入规模,f(n)为语句关于n所占存储空间的函数。

案例:反转数组

public static int[] reverse1(int[] arr){
int n=arr.length;//申请4个字节
int temp;//申请4个字节
for(int start=0,end=n-1;start<=end;start++,end--){
temp=arr[start];
arr[start]=arr[end];
arr[end]=temp;
}
return arr;
}
public static int[] reverse2(int[] arr){
int n=arr.length;//申请4个字节
int[] temp=new int[n];//申请n*4个字节+数组自身头信息开销24个字节
for (int i = n-1; i >=0; i--) {
temp[n-1-i]=arr[i];
}
return temp;
}
  • 根据大O推导法则,算法一的空间复杂度为O(1),算法二的空间复杂度为O(n),所以从空间占用的角度讲,算法一要 优于算法二。
  • 由于java中有内存垃圾回收机制,并且jvm对程序的内存占用也有优化(例如即时编译),我们无法精确的评估一 个java程序的内存占用情况,但是了解了java的基本内存占用,使我们可以对java程序的内存占用情况进行估算。
  • 我们可以不用太注意空间复杂度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长安不及十里

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

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

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

打赏作者

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

抵扣说明:

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

余额充值