算法分析

算法分析描述

根据数据规模n,分析运行时间(时间复杂度分析)和内存使用情况(空间复杂度分析)

定义

  1. n: 数据规模
  2. O(n): 增长函数,又称为增长率。算法的运行时间或内存使用随着数据规模的变化而变化。用于表示时间复杂度和空间复杂度分析。
    例如: 时间复杂度:O(1000) , 算法的运行时间为1000s,具体看运行平台,这里只是假设。

情况分析

对于n一样,不同的数据会造成不同的运行时间,分为三种情况,一般我们只分析它的最坏情况。下面以数据结构查找二叉树为例:
二叉树例子

  1. 最好情况: 左子树和右子树高度相等。查找元素时间复杂度O(logn)在这里插入图片描述

  2. 最坏情况:元素往一边倾倒,退化成链表。查找元素时间复杂度O(n)
    在这里插入图片描述

  3. 平均情况:O( l o g n log_n logn)

增长率

下面以运行时间来解释,增长率表达 时间复杂度 和 空间复杂度是一样的方式表达。由快到慢排序

  1. O(1): 常数级别。使用的时间是固定,于n无关。O(8) = 10s, O(1000) = 10s
  2. O(logn): 对数级别。每次处理数据将数量减少一半。O(8) = log2^8 = 3s
  3. O(n): 线性级别。数据有多少,就处理多少次。O(8) -> 8s
  4. O(nlogn): 线性对数级别。O(8) = 8*3 = 24
  5. O( n 2 n^2 n2):平方级别。O(8) = 64
  6. O( 2 n 2^n 2n): 指数级别。O(8) = 256
  7. O(n!): 阶乘级别。O(8) = 40320

https://www.bigocheatsheet.com/

例子

下面我们已具体的算法例子求增长率
O(1)
数组的访问

array[0]

解释:数组的访问,不管有多少数据量,访问永远是1。因为数组在内存中的位置是连续的,我们知道数组的开始位置,比如是1,那么访问某个元素array[1000] = 1*1000 = 1000那个位置
Leetcode数据介绍

O(logn)
查找二叉树的查找操作
在这里插入图片描述

解释:查找过程,比当前元素小,去左边继续查找,大于去右边继续查找。从上图就可以轻易算出,一共比较了三次。O(log2^8) = 3

O(n)

// 查找元素
for (let i=0; i<array.length; i++) {
    if (array[i] == 10) {
    	break;
    }
}

解释:如果目标元素在最后一个位置,那么就要遍历到最后的位置。O(1000) = 1000
O( n 2 n^2 n2)

let count = 1000;
let target = 506;
let result = 0;
for(let i=1; i<=count; i++) {
  for (let j=1; j<=count; j++) {
	  if (i+j===target) {
        result++;
      }
  }
}

解释:双重循环

问题描述:在1000个数内,找出3个相加和为506有多少个

// js
let count = 1000;
let target = 506;
let result = 0;
for(let i=1; i<=count; i++) {
  for (let j=1; j<=count; j++) {
    for (let k=1; k<=count; k++) {
      if (i+j+k===target) {
        result++;
      }
    }
  }
}

分析具体运行时间

运行时间T(n) = a * 增长函数
a: 常数。具体看运行机器,可以理解为执行每条语句的耗时
增长函数:语句运行的次数。通常为循环语句、函数调用的次数

  1. 求出增长函数:O(n^3)。因为这里有3层循环,其他语句可以忽略不计
  2. 求出运行时间,这里需要实际运行一下
// js
        function testRunTime(fn) {
            let start = new Date();
            let end = null;
            fn();
            end = new Date();
            console.log(`运行时间: ${(end - start) / 1000}秒`); // 1.718 秒
        }
        testRunTime(() => {
            let count = 1000;
            let target = 506;
            let result = 0;
            for (let i = 1; i <= count; i++) {
                for (let j = 1; j <= count; j++) {
                    for (let k = 1; k <= count; k++) {
                        if (i + j + k === target) {
                            result++;
                        }
                    }
                }
            } 
        });
  1. 求出a: 1.718 / 1000^3 = 0.000000001718
  2. 得到时间计算模型: T(n) = 0.000000001718 * n^3(秒)

注意事项

  1. 如果算法中除了循环或函数调用,有较大的语句运行,也要计算进去。如 O(n) = n + 100
  2. 增长函数并非只是统计循环、函数调用。

分析内存使用情况

算法运行时所创建的数据类型的内存占用大小总和

  1. 找出算法运行时创建的数据类型:
    5个数字类型变量。因为for循环中定义的变量是局部变量,每一次循环结束都会销毁,故算一次
  2. 找出数据类型占用的内存大小,将全部相加
    假设每个数据类型占用内存为4字节,则5*4=20字节
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值