算法笔记-算法基础知识

1.什么是算法?

算法是一种解决某类问题具体的明确无歧义计算过程

2.数量级

十进制的指数。

例如: 1500 = 1.5*(10**3)数量级是3,也可以是 “千”,kilo

          150万 = 1.5*(10**6) 数量级是6, 也可以是“百万”, ‘million’

          150万比1500大3个数量级

3.输入规模

执行环境资源有限,需要根据输入规模(数量级)准备资源,比预估的高一个数量级就可以。

例如: React的VirtualDOM 应该支持[万]数量级数据(默认页面最大节点数在“千”级),在“毫秒”时间内完成一次计算。

因为:显示器更新时间时间间隔10ms,算法应该<这个数量级,为了显示器显示不卡

4. 算法依赖的数学模型

CPU包含:

短期记忆(寄存器-Register)

推理计算(算法逻辑单元-ALU-Arithmetic and Logic Unit)

系统将数据从内存读取到寄存器,计算完成后再存回内存

内存:

长期记忆(随机存储器-RAM-数据空间地址+指令空间地址)

访问每个地址时间相同

例如:5000*0.2=1000; 数据计算时都要在寄存器中,结果返回也返回到寄存器中

 5. 算法的时间复杂度和空间复杂度

时间复杂度和空间复杂度都是对算法的一个分类

时间复杂度

在该算法中执行次数最多的代码行,执行的次数,表示时间复杂度。因为每个命令,代表固定的指令和CPU执行周期,代表固定的时间。

时间复杂度分类

示例

          长度为n的一维数组遍历-----O(n)
          n*n的二维数组嵌套遍历 --------O(n^2)
          n*n*n的三维数组嵌套遍历------O(n^3)
          n*m的二维数组嵌套遍历-----------O(n*m)
          长度n的数组和m的数组分别遍历----O(n+m)
          运算次数为常数---------------O(1)

空间复杂度

空间复杂度是指算法用了多少额外的空间,可以理解成新创建了多少空间。没有额外创建的话O(1)

空间复杂度分类的表示方法和时间复杂度雷同。

例如:

// 实现长度为n的数组的反转
function f(A) {
  const reverseA = []; 
  for(let i=0; i<A.length; i++) {
    reverseA.push(A.pop(A))
  }
  return reverseA; // 相当于创建了一个长度为n的空间,复杂度O(n)
}

上面的方法如果想要实现空间复杂度O(1)。则只能在原来数组

// 实现长度为n的数组的反转
function f(A) {
  let l = 0, r=A.length-1;
  while(l<r) {
    let temp = A[l];
    A[l++] = A[r];
    A[r--] = temp;
  }
}

 ⚠️对于递归算法,函数参数所占用的空间会累计。

6.复杂度的本质

复杂度是一种度量指标(消耗时间和空间)随着输入规模增长而增常的一种关系。根据不同的关系有不同的分类。

O(1)+O(1)=O(1);
O(n)+O(n)=O(n);
O(lgn)+O(lgn)=O(lgn);
O(lgn)+O(n)=O(n);
O(n)+O(1)=O(n);
O(n^2)+O(n)=O(n^2);

由上面可知,复杂度是以最大消耗作为计算。

O其实是复杂度的渐近上界(最坏的情况)。

Ω是复杂度渐近下界(最好);𝚯是渐近紧密界(中间)。

复杂度分类 O(1),O(lgn), O(√n),O(n),O(nlgn),O(n^2),O(2^n),O(n!)

绿色部分是单机一般能解决;黄色需要用集群等;红色部分属于宕机算法。

降低复杂度的方法:

// 分治策略
O(n^2) -> O(nlgn)
// 散列
O(n) -> O(1)
O(n) -> O(k)
// 二叉树
O(n) -> O(lgn)
// 链表
O(n) -> O(1)
// 动态规划
O(2^n) -> O(n^2)
O(n!) -> O(n^2)

 

posted @ 2019-09-14 15:42  Lyra李  阅读(829)  评论(0编辑  收藏  举报