第一章


1.1 计算

计算机只是我们的工具(手段),我们研究的对象是计算

计算 = 信息处理

借助某种工具,遵照一定规则,以明确而机械的形式进行。

机器模型 = 计算机 = 信息处理工具

所谓算法,即特定计算模型下,旨在解决特定问题的指令序列

  • 输入,待处理的信息(问题)
  • 输出,经处理的信息(答案)
  • 正确性,的确可以解决指定的问题
  • 确定性,任一算法都可以描述为一个由基本操作组成的序列
  • 可行性,每一基本操作都可实现,且在常数时间内完成
  • 有穷性,对于任何输入,经有穷次基本操作,都可以得到输出

好算法的定义

  • 正确,对于输入有正确的输出
  • 健壮,对于不合法的操作,可以恢复程序的正常执行
  • 可读,结构化+准确命名+注释+ ···
  • 效率,速度尽可能快,存储空间尽可能少

程序 = 数据结构 + 算法

要改进或者优化某个算法,我们需要先知道这个算法的效率。

算法分析

  • 正确性,算法功能与问题要求是否一致
  • 成本,运行时间+所需存储空间

通常我们对一个算法的度量值的大小都这个度量规模的最坏情况

对于特定问题+不同算法,我们该如何判断其优劣呢?考察以下两种模型

  • TM模型(图灵机)。
  • RAM模型(汇编)。

我们度量的单位为CPU的执行次数,算法在必要的时候需要复位


大 O 记号

n为问题规模

常系数可忽略:

O(f(n))=O(c∗f(n))O(f(n))=O(c∗f(n))

O( f(n) ) = O( c * f(n) )
低次项可忽略:

O(na+nb)=O(na),a>b>0O(na+nb)=O(na),a>b>0

O( n^a + n^b ) = O(n^a) , a>b>0

其他记号:

  • Big Ω,最大下界。
  • Big θ ,折中。

O的等级:

  • 常数,O(1)
  • 对数,O(logn),以2为底数
  • 多项式,O(n^c)
  • 线性复杂度,O(n)
  • 指数复杂度,O(2^n)

算法效率从O(2^n)到O(n^c)是一个难点。通常情况下,我们想找出一个效率从指数到多项式的算法是非常难的。这是一个分水岭

定理:2-Subset is NP-complete。解释:就目前的计算模型而言,不存在可在多项式时间内回答此问题的算法。

NP问题就是一个幂集问题,效率为O(2^n)。


算法分析

两个主要任务 = 正确性( 不变性*单调性 ) + 复杂度

C++等高级语言的基本指令,均等效于RAM的基本指令;在渐进意义下,二者大体相当。

复杂度分析的主要方法:

  • 迭代:级数求和

    • 算术级数:与末项的平方同阶
    • 幂方级数:比幂次高出一阶
    • 几何级数:与末项同阶
    • 收敛级数:常数 O(1)(某种情况下是有意义的,比如迭代的去投掷一枚硬币,直到出现正面)
    • 调和级数:O(logn)
    • 对数级数:O(nlogn)
    • …(有一本书叫做《具体数学》)
  • 递归:递归跟踪 + 递推方程
  • 猜想 + 验证

迭代与递归

迭代乃人工,递归方神通

从效率上讲,迭代效率比递归效率要来的高。我们需要学习的是从递归到迭代的一个过程。

凡治众如治寡,分数是也

对于一个问题,分成一系列子问题。通过求解子问题进而得出这个问题的解。

减而治之与分而治之


动态规划

第一个例子:斐波那契数列

递归版本的fib和迭代版的fib的效率相差巨大(原因重新计算已经被计算过的fib数)。

//递归版
int fib(int n){return (2>n)? n : fib(n-1) + fib(n-2);
}

很明显这是求解一个幂集问题,这段代码时间复杂度是2的n次方,空间复杂度是O(n)。

改进1:记忆版本(制表)

//迭代
int arr[] = new int[n+1];
arr[1] = 1;
arr[2] = 1;
for(int i=3;i<n;i++){arr[i] = arr[i-1]+arr[i-2];
}
return arr[n];

以上时间复杂度和空间复杂度都是O(n)。

改进2:动态规划(自底而上)

//迭代
int f=0,g=1;
while(0<n--){g = g+f;f = g-f;
}
return g;

时间复杂度是O(n),空间复杂度是O(1)。

第二个例子:LCS序列

递归版(算法步骤):
对于序列 A[0, n] 和 B[0, m] 无非三种情况

  1. 若 n= -1 或 m= -1,则取作空序列(“”)
  2. 若 A[n]= ‘X’ =B[n],则取作LCS( A[0,n), B[0,m) ) + ‘X’
  3. A[n] != B[n],则在 LCS( A[0,n], B[0,m)) 与 LCS( A[0,n), B[0,m]) 中取更长者
public static String LCS(char A[],int alo,int ahi,char B[],int blo,int bhi){//第一种情况if(ahi==-1||bhi==-1){return "";}//第二种情况if(A[ahi]==B[bhi]){return LCS(A,alo,ahi-1,B,blo,bhi-1)+A[ahi];}//第三种情况,由于这种情况将问题分成2个子问题。else{String AA = LCS(A,alo,ahi-1,B,blo,bhi);String BB = LCS(A,alo,ahi,B,blo,bhi-1);return AA.length()>BB.length()? AA : BB;}
}

明显是一个幂集问题,所以时间复杂度为O(2^n),空间复杂度为O(n)

由递归分析,我们得出一个结论,重复元素多次计算,所以我们可以改进。

迭代版(制表):

  1. 第一行和第一列初始化为0
  2. 若行和列所对应的字母相等,则table[i][j] = table[i-1][j-1]
  3. table[i][j] 取 table[i-1][j] 和 table[i][j-1] 更大者
public static void main(String[] args) {//测试数据String A = "DATA";String B = "NAA";int n = A.length();int m = B.length();//start LCS//初始化int table[][] = new int[n+1][m+1];for(int i=0;i<n;i++){table[i][0] = 0;}for(int j=0;j<m;j++){table[0][j] = 0;}//迭代for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){//第二种情况,由于字符串是从0开始,而表格是从1开始,所以对于的table和字符串相差1if(A.charAt(i-1)==B.charAt(j-1)){table[i][j] = table[i-1][j-1]+1;}//第三种情况else{table[i][j] = table[i-1][j]>table[i][j-1] ? table[i-1][j] :table[i][j-1];}}}//end LCS//测试结果int count = 1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(table[i][j]==count){System.out.print(A.charAt(i-1));count++;}}}System.out.println();}

显然时间复杂度和空间复杂度都为O(n*m)

数据结构与算法---笔记相关推荐

  1. 数据结构与算法笔记 - 绪论

    数据结构与算法笔记 - 绪论 1. 什么是计算 2. 评判DSA优劣的参照(直尺) 3. 度量DSA性能的尺度(刻度) 4. DSA的性能度量的方法 5. DSA性能的设计及其优化 x1. 理论模型与 ...

  2. 数据结构与算法笔记(十六)—— 二叉搜索树

    一.二叉搜索树定义 二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree). 二叉搜索树是具有有以下性质的二叉树: 若左子树不为空,则左子树上所有节点的 ...

  3. 数据结构与算法笔记(十五)—— 散列(哈希表)

    一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...

  4. 数据结构与算法笔记(青岛大学王卓老师视频)

    写在前面的话: 因为在学习数据结构之前,学习过一年的算法,所以有一些基础,一些我觉得 没必要的代码或知识就没写上,记得多是一些知识点,写的可能对于别人来说 很难接受,望谅解.我学习算法是在Acwing ...

  5. JS数据结构与算法 笔记

    JS数据结构与算法笔记 前言:不定时更新说明 1. 栈(Stack) 1.1 基于数组实现栈 1.2 基于对象实现栈 1.3 基于链表实现栈 1.4 栈的简单应用 1.4.1 字符串中的括号匹配问题 ...

  6. 数据结构与算法笔记(王卓网课+教材+大话数据结构)

    数据结构与算法笔记(王卓网课+教材+大话数据结构) ##最新整理!!! 顺序存储结构的线性表P10-P21 顺序线性表的代码实现 链式线性表笔记 串笔记 绪论.算法(P1-P9)1.4数据起源结构 数 ...

  7. 明翰数据结构与算法笔记V0.8(持续更新)

    文章目录 前言 数据结构 `线性表` `数组` `链表` `栈与队列` [串/字符串] 树 并查集 `二叉树` [二叉排序树/二叉搜索树] `红黑树` 红黑树操作 霍夫曼树 `堆` [大/小]根堆 可 ...

  8. Java版数据结构与算法笔记

    文章目录 一.数据结构与算法概述及题目 1.数据结构和算法的关系 2.线性结构与非线性结构 Ⅰ-线性结构 Ⅱ-非线性结构 3.经典面试题 Ⅰ-字符串匹配问题: Ⅱ-汉诺塔游戏 Ⅲ-八皇后问题: Ⅳ-马 ...

  9. 清华大学博士讲解Python数据结构与算法笔记

    清华大学博士讲解Python数据结构与算法的笔记 Notion 连接: https://fine-individual-553.notion.site/Python-2bf3c87f1c504d758 ...

  10. 数据结构与算法笔记 —— 十大经典排序及算法的稳定性

    一.十大经典排序算法 排序算法是<数据结构与算法>中最基本的算法之一. 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全 ...

最新文章

  1. 堆、栈、方法区、静态代码块---Java
  2. CSS sprites
  3. pgpool-II中间件
  4. JS和C#访问遇到QueryInterface调用出错
  5. 我的世界服务器怎么修改书与笔,我的世界书与笔怎么做 我的世界书与笔怎么用...
  6. 如何将电子海图的航线导到gps上_电子海图(ECDIS)使用总结
  7. 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)
  8. 6. 以下耦合度中最松散的耦合是_什么是程序设计中的高内聚、低耦合?
  9. ssh-keygen的使用方法及配置authorized_keys两台linux机器相互认证
  10. Python | 计算给定数字的平方(3种不同方式)
  11. Ada2012即将完成
  12. 【JS】使用jQuery制作图片手风琴效果
  13. 吴恩达机器学习笔记-无监督学习
  14. CSS 帧动画 播放动画
  15. 中职计算机老师的一天,信息技术教师的一天
  16. java中ws程序是什么意思_Java Web服务对象(JAX-WS)生命周期
  17. 聚焦爬虫与通用爬虫详解
  18. 连续自然数平立方求和推导
  19. 最长不下降子序列O(NlogN) 输出序列
  20. Maven 虐我千百遍,我待 Maven 如初恋 侵删

热门文章

  1. nyoj 42 一笔画问题 (搜索+队列)
  2. 【洛谷 3372】线段树 1
  3. 2-2 工程源码文件结构
  4. 递归删除目录下.svn文件
  5. 解决springmvc在单纯返回一个字符串对象时所出现的乱码情况(极速版)
  6. openstack-networking-neutron(四)--iptables
  7. OllyDbg 使用笔记 (十二)
  8. .net框架、CLR和C#的版本之间的对应关系
  9. linux 0.11 内核学习 -- rs_io.s,串口汇编代码
  10. Dragon Quest VIII 流程攻略(繁体中文完结版)