数据结构与算法刷题汇总

方法:leetcode打基础+剑指Offer针对性训练

文章目录

    • 【数据结构】
      • 数组✌
      • 字符串✌
      • 链表✌
      • 树✌
      • 栈&优先队列✌
      • 并查集
      • 字典树
      • 矩阵
    • 【算法】
      • 递归和循环
      • 查找和排序
      • 回溯法
      • 动态规划和贪婪算法
      • 位运算
      • DFS&BFS
      • 随机
      • 数学
      • 设计
    • 高质量的代码
      • 代码的规范性:清晰的书写、清晰的布局和合理的命名。
      • 代码的完整性:功能测试、边界测试和负面测试。
      • 代码的鲁棒性
    • 解决面试题的思路
      • 画图
      • 举例
      • 分解

【数据结构】

数组和字符串是两种最基本的数据结构,它们用连续内存分别存储数字和字符。链表和树是面试中出现频率最高的数据结构。栈是一个与递归紧密相关的数据结构,同样队列也与广度优先遍历算法紧密相关。

数组✌

大小固定、内存连续、简单哈希表、动态数组

【面试题3】(不修改)找出数组中的重复数字

【面试题4】二维数组中的查找

字符串✌

字符组成、常量字符串、数组字符串

【面试题5】替换空格

基础

  1. 【13.罗马数字转整数】简单
  2. 【12.整数转罗马数字】中等
  3. 【273.整数转换英文表示】困难

提高

  1. 【68. 文本左右对齐】困难
  2. 【65.有效数字】困难

子串

  1. 【76. 最小覆盖子串】困难
  2. 【30. 串联所有单词的子串】困难
  3. 【3. 无重复字符的最长子串】中等
  4. 【395.至少有K个重复字符的最长子串】中等

回文串

  1. 【125. 验证回文串】
  2. 【5. 最长回文子串】
  3. 【214.最短回文串】
  4. 【336.回文对】
  5. 【131.分割回文串&132.分割回文串Ⅱ】

括号

  1. 【20.有效的括号】
  2. 【22.括号生成】
  3. 【32.最长有效括号】
  4. 【241.为运算表达式设计优先级】
  5. 【301.删除无效的括号】

子序列

  1. 【115.不同的子序列】

链表✌

面试最频繁、代码量适中、空间效率高、环形链表、双向链表、复杂链表

  1. 【206.反转链表】
  2. 【141.环形链表】
  3. 【24.两两交换链表中的节点】
  4. 【328.奇偶链表】
  5. 【92.反转链表Ⅱ】
  6. 【237.删除链表中的节点】
  7. 【19.删除链表的倒数第N个节点】
  8. 【301.删除无效的括号】
  9. 【203.移除链表元素】
  10. 【83.删除排序链表中的重复元素】
  11. 【82. 删除排序链表中的重复元素 II】
  12. 【160.相交链表】
  13. 【21.合并两个有序链表】
  14. 【143.重排链表】
  15. 【142.环形链表Ⅱ】
  16. 【148.排序链表】
  17. 【25.K个一组翻转链表】
  18. 【61.旋转链表】
  19. 【86.分隔链表】
  20. 【23.合并K个排序链表】
  21. 【147.对链表进行插入排序】

树✌

二叉树:前序、中序、后序遍历的递归和迭代写法、层次遍历(宽度优先遍历)、二叉搜索树、堆和红黑树

【面试题7】重建二叉树】

【面试题8】二叉树的下一个节点

遍历基础(递归+迭代)

  1. 【144.二叉树的前序遍历】中等
  2. 【94.二叉树的中序遍历】中等
  3. 【145.二叉树的后序遍历】中等
  4. 【102.二叉树的层次遍历】中等

遍历的应用

  1. 【100.相同的树】简单
  2. 【101.对称二叉树】简单
  3. 【226.翻转二叉树】
  4. 【257.二叉树的所有路径】
  5. 【112.路径总和】
  6. 【113.路径总和Ⅱ】
  7. 【124.二叉树中的最大路径和】
  8. 【129.求根到叶子节点数字之和】
  9. 【111.二叉树的最小深度】
  10. 【104.二叉树的最大深度】
  11. 【110.平衡二叉树】
  12. 【337.打家劫舍Ⅲ】
  13. 【107.二叉树的层次遍历Ⅱ】
  14. 【103.二叉树的锯齿形层次遍历】
  15. 【199.二叉树的右视图】

二叉搜索树

  1. 【98.验证二叉搜索树】
  2. 【235.二叉搜索树的最近公共祖先】
  3. 【236.二叉树的最近公共祖先】
  4. 【108.将有序数组转换为二叉搜索树】
  5. 【109.有序链表转换二叉搜索树】
  6. 【173.二叉搜索树迭代器】
  7. 【230.二叉搜索树中第K小的元素】
  8. 【297.二叉树的序列化和反序列化】
  9. 【99.恢复二叉搜索树】
  10. 【116.填充每个节点的下一个右侧节点指针】
  11. 【117.填充每个节点的下一个右侧节点指针Ⅱ】
  12. 【96.不同的二叉搜索树】

栈&优先队列✌

栈:后进先出,无序
队列:先进先出

【面试题9】用两个栈实现队列

  1. 【155.最小栈】
  2. 【232.用栈实现队列】
  3. 【225.用队列实现栈】
  4. 【150.逆波兰表达式求值】
  5. 【71.简化路径】
  6. 【388.文件的最长绝对路径】
  7. 【394.字符串解码】
  8. 【224.基本计算器】
  9. 【227.基本计算器Ⅱ】
  10. 【385.迷你语法分析器】
  11. 【84.柱状图中最大的矩形】
  12. 【215. 数组中的第K个最大元素】
  13. 【347.前K个高频元素】
  14. 【218.天际线问题】
  15. 【332.重新安排行程】
  16. 【341.扁平化嵌套列表迭代器】

并查集

字典树

矩阵

【算法】

一般算法具有递归和循环两种实现方式,递归简洁但性能不佳;排序和查找是重点,需重点掌握二分查找、归并排序和快速排序;二维数组搜索路径,使用回溯法,适合递归实现;求某个问题最优解,该问题可分为多个子问题,使用动态规划,为避免重复计算,使用自下而上的循环代码实现;分解子问题时存在某个特殊选择,且能得到最优解,适用贪婪算法,并证明贪婪算法能够得到最优解;位运算,包括与、或、异或、左移和右移。

递归和循环

适用于重复计算多次相同的问题,如无特别要求,优先使用递归写法。
递归的本质是将一个问题分解为两个或多个小问题,但是其中很多计算可能都是重复的,对性能带来很大影响。

动态规划解决问题是一般用递归思路分析问题,由于递归分解的子问题中存在大量重复,因此我们用自下而上的循环来实现代码。

递归可能导致调用栈溢出。

【面试题10】斐波那契数列

查找和排序

查找:顺序查找、二分查找、哈希表查找和二叉排序树查找。

排序:插入排序、冒泡排序、归并排序、快速排序的特点,从额外空间消耗、平均时间复杂度和最差时间复杂度等方面比较优缺点。

【面试题11】旋转数组的最小数字

回溯法

=蛮力法“升级版”,适合解决多步骤问题,每个步骤有多个选项,适合递归实现。

将回溯法解决问题的选项用树结构表示,步骤看做为一个节点,选型对应着节点连接线。叶节点不满足约束条件则往上回溯尝试。

【面试题12】矩阵中的路径

【面试题13】机器人的运动范围

动态规划和贪婪算法

动态规划:求一个问题最优解(通常是最大最小值),该问题能够分解成若干个子问题,且子问题之间还有重叠的更小的子问题。 应用动态规划求解问题的特点:
一,求一个问题的最优解;
二,整体问题的最优解依赖各个子问题的最优解;
三,大问题分解成若干小问题,小问题之间有互相重叠的更小的子问题;
四,从上往下分析问题,从下往上求解问题。
贪婪算法:每一步做出一个贪婪的选择,基于这个选择,可以确定能够得到最优解。

【面试题14】剪绳子

位运算

位运算:把数字用二进制表示之后,对每一位上0或1的运算。包括与、或、异或、左移和右移五种运算。
左移运算符m<>n表示把m右移n位,右边n位丢弃。
右移无符号数值,用0填充左边n位;右移有符号数,正数用0填充,负数用1填充左边n位。

【面试题15】二进制中1的个数

DFS&BFS

随机

数学

设计

高质量的代码

代码的规范性:清晰的书写、清晰的布局和合理的命名。

代码的完整性:功能测试、边界测试和负面测试。

优点 缺点
返回值 和系统API一致 不能方便的使用计算结果
全局变量 能够方便的使用计算结果 用户可能会忘记检查全局变量
异常 可以为不同的出错原因定义不同的异常类型 有些语言不支持异常,抛出异常时对性能有负面影响

【面试题17】打印从1到最大的n位数

【面试题18】删除链表的节点

【面试题19】正则表达式匹配

【面试题20】表示数值的字符串

【面试题21】调整数组顺序是奇数位于偶数前面

代码的鲁棒性

鲁棒性指程序能判断输入是否合乎规范要求,并对不符合要求的输入予以合理的处理。
容错性、防御性编程、

【面试题22】链表中倒数第k个节点

【面试题23】链表中环的入口节点

【面试题24】反转链表

【面试题25】合并两个排序的链表

【面试题26】树的子结构

大多数面试都要求应聘者在白纸或者白板上写代码。应聘者应该在编码的时候注意规范性,尽量清晰的书写每个字母,通过缩进和对其括号让代码布局合理,同时合理命名代码中的变量和函数。
最好在编码之前全面考虑所有可能的输入,确保写出的代码在完成了基本功能之外,还考虑了边界条件,并做好了错误处理。只有全面考虑到这3个方面的代码才是完整的代码。
另外,要确保自己写出的程序不会轻易崩溃。平时在写代码的时候,最好养成防御性编程的习惯,在函数入口判断输入是否有效,并对各种无效输入做好相应的处理。

解决面试题的思路

画图

举例

分解

你可能感兴趣的:(朱滕威的面试之路)