数据结构与算法(一)——20200902

尚硅谷—java数据结构与算法—韩顺平

内容介绍

几个经典的面试题

  • 字符串匹配问题

    • 要求
    1. 两个字符串: str1=“abcabdabe”,str2=“abd”
    2. 判断str1中是否包含str2,如果存在,就返回第一次出现的位置,如果没有返回-1.
    3. 用最快的速度来完成匹配
    • 暴力匹配:简单、效率低
    • KMP算法(部分匹配表)
  • 汉诺塔

    • 要求:
      1. 将A塔的所有圆盘移动到C塔上
      2. 小圆盘不能放在大圆盘的下面
      3. 每次只能移动一个圆盘
    • 分治问题
  • 八皇后问题

    • 任意两个皇后不能处于同一行同一列或同一斜线上,有多少种摆法
    • 回溯算法
  • 马踏棋盘

    • 8x8棋盘。马走日,要求每个放个之进入一次,走遍棋盘格上全部64个方格
    • 图的DFS+贪心算法优化
  • 修路问题

    • 最小生成树(普利姆算法)
  • 最短路径问题

    • 弗洛伊德算法

重要性

  1. 算法是程序的灵魂
  2. 使用内存计算框架(Spark)和缓存技术(Redis)来优化程序,这些计算框架和缓存技术,它们的核心?
  3. 实际开发,算法影响性能
  4. 面试需求

数据结构和算法概述

数据结构和算法的关系

  • 数据结构(data structure)是一门研究组织数据方式的学科,有了编程语言也就有了数据结构,学好数据结构就可以编写出更加漂亮、有效率的代码
  • 要学好结构要多多考虑如何将生活中的问题,用程序去实现解决
  • 程序=数据结构+算法
  • 数据结构是算法的基础

线性结构和非线性结构

线性结构:

  1. 数据元素存在一对一的关系
  2. 顺序存储结构和链式存储结构
  3. 常见的有数组、队列、链表和栈
    非线性结构:
    常见的有:二维数组,多维数组,广义表,树结构,图结构

稀疏数组

需求背景:五子棋程序,有存盘退出和继续上盘的功能。(或地图)

可以想到用二维数组记录棋盘,但其中很多值是默认值0,因此记录了很多没有意义的数据。 —》于是用稀疏数组来优化。

当一个数据中大部分元素是0,或者为同一个值时,可以用稀疏数组来保存该数组。

稀疏数组的处理方法:

  1. 记录数组一共有几行几列,有多少个不同的值
  2. 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

例如:

index
0678
10322
20615
33506

代码实现:

原始数组==》稀疏数组:

  1. 遍历原始的二维数组,得到有效数组的个数sum
  2. 根据sum创建稀疏数组int[sum+1][3]
  3. 将二维数组的有效数据存入到稀疏数组

稀疏数组==》原始数组:

  1. 读取第一行,创建原始二维数组
  2. 读取后几行的数据,赋给原始数组

队列(略)

数组模拟队列(略)

单链表

单链表面试题

  1. 求单链表中节点个数
  2. 查找单链表中倒数第k个结点
  3. 单链表的反转——遍历之后插入新链表(头插/尾插)
  4. 从尾到头打印单链表
    1. 反向遍历
    2. Stack
  5. 合并两个有序的单链表
    1. 合并K个有序的单链表

双向链表(略)

环形链表和约瑟夫Josephu问题

综合计算器

  • 两个栈:
    • 数栈(存放数字,类似操作数栈)
    • 符号栈(存放运算符)
  • 当前符号和符号栈的比较
    • 当前符号栈为空:直接入栈
    • 当前符号优先级栈 < = <= <=栈顶符号:计算栈顶符号和数栈的结果,再分别把结果和当前符号入栈
    • 当前符号优先级栈 > > >栈顶符号:直接入符号栈
前缀表达式(波兰表达式)
  • 前缀表达式的运算符位于操作数之前。
  • 举例: ( 3 + 4 ) ∗ 5 − 6 (3+4)*5-6 (3+4)56对应的前缀表达式是 − ∗ + 3456 -*+3456 +3456
  • 计算机求值流程:
    • 从右至左扫描,将 6、5、4、3压入堆栈。
    • 遇到 + + +运算符,弹出3和4,计算 3 + 4 3+4 3+4的值,为7,压入栈。
    • ∗ * 运算符,得到35,入栈。
    • − - 运算符,得到29,即为最终结果。
    • 将堆栈元素依次取出,即为前缀表达式
中缀表达式
  • 中缀表达式就是常见的运算表达式。如 ( 3 + 4 ) ∗ 5 − 6 (3+4)*5-6 (3+4)56
  • 中缀表达式是人熟悉的,但确实计算机不好操作的。通常改写为后缀表达式
后缀表达式(逆波兰表达式)
  • 与前缀表达式相似,只是运算符位于操作数之后。
  • 举例: ( 3 + 4 ) ∗ 5 − 6 (3+4)*5-6 (3+4)56对应的后缀表达式是 34 + 5 ∗ 6 − 34+5*6- 34+56
  • 针对后缀表达式求值步骤:
    • 从左至右扫描,把3和4压入堆栈
    • 遇到+运算符,因此弹出4和3,计算值为7,入栈。
    • 将5入栈
    • 遇到*运算符,弹出5和7,计算出值35,入栈
    • 将6入栈
    • 遇到-运算符,计算出值29,即为最后结果。
  • 后缀表达式符合计算机运算的逻辑顺序
正常表达式后缀表达式
a + b a+b a+b a b + ab+ ab+
a + ( b − c ) a+(b-c) a+(bc) a b c − + abc-+ abc+
a + ( b − c ) ∗ d a+(b-c)*d a+(bc)d a b c − d ∗ + abc-d*+ abcd+
a + d ∗ ( b − c ) a+d*(b-c) a+d(bc) a d b c − ∗ + adbc-*+ adbc+
a = 1 + 3 a=1+3 a=1+3 a 13 + = a13+= a13+=

逆波兰计算器

  1. 将中缀表达式转换为逆波兰表达式
  2. 输入逆波兰表达式,使用栈,计算结果
  3. 支持小括号和多位数整数。

中缀表达式转后缀表达式

  1. 初始化两个栈:运算符栈1和中间结果栈2
  2. 从左至右扫描中缀表达式
  3. 遇到操作数时,压入s2 。
  4. 遇到运算符时,比较其与s1栈顶运算符的优先级:
    1. 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈。
    2. 否则,若优先级比 栈顶运算符高,也将运算符压入s1。
    3. 否则,将s1栈顶的运算符弹出并压入s2中,再次转到(4-1)与s1中新的栈顶运算符相比较。
  5. 遇到括号时
    1. 若为左括号“( ”,则直接压入s1
    2. 若为右括号“ )”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃。
  6. 重复步骤(2)-(5) ,直到表达式的最右边
  7. 将s1中剩余的运算符依次弹出并压入s2
  8. 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

递归

迷宫问题

  • map[m][n] 二维数组表示地图:
    • 0:没有走过
    • 1:表示墙
    • 2:通路可以走
    • 3:已经走过,但是走不通
  • 确定一个策略:下 => 右 => 上 => 左;走不通,再回溯
  • 最短路径
    • 路径和策略有关——策略遍历,比较

八皇后问题(回溯算法)

  1. 暴力解法
  • 用一维数组表示棋盘,八皇后的位置arr[8] = {0,4,7,5,2,6,1,3} :数组下标表示row,数组值表示col。
  • 判断是否是同一斜线: Math.abs(i-j)==Math.abs(arr[i]-arr[j])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值