❤️大厂面试基础算法总结❤️(强烈推荐)

文章目录

  • 一、前言
  • 二、数据结构
    • 1、单向链表
      • 1)链表的删除
      • 2)链表的翻转
      • 3)链表的快慢指针
    • 2、双向链表
    • 3、栈
    • 4、二叉树
  • 三、算法
    • 1、排序
    • 2、二分枚举
    • 3、广度优先搜索
    • 4、深度优先搜索
    • 5、动态规划
      • 1)递推
      • 2)子段最优值
      • 3)区间 DP
      • 4)二维DP
    • 6、贪心
    • 7、尺取法
    • 8、字符串模拟
    • 9、树状数组
    • 10、模拟
    • 11、位运算

一、前言

  最近发现了一个网站,叫 牛客网(www.nowcoder.com),看了看上面的题目,普遍偏简单,于是找回了大学时候刷题的快感,赶紧来刷一刷。选了一个企业,把它的面试题刷完了。
❤️大厂面试基础算法总结❤️(强烈推荐)_第1张图片
  大致做一波总结,如果有小伙伴有兴趣的,可以照着我的目录来刷,所有题目基本都属于没有很强算法基础就能做的,分成两大块内容:数据结构 和 算法。数据结构包含:链表、队列、栈、二叉树。算法包含:排序、二分枚举、搜索、动态规划、贪心、位运算应用、模拟等等。


在这里插入图片描述


二、数据结构

1、单向链表

1)链表的删除

  • 单向链表的删除,需要先找到这个结点,并且记录它的前驱结点,让前驱结点指向它的后继结点,整个过程最坏时间复杂度为 O ( n ) O(n) O(n),主要是遍历的时间复杂度,删除结点这个操作本身是 O ( 1 ) O(1) O(1) 的。
    ❤️大厂面试基础算法总结❤️(强烈推荐)_第2张图片
题目链接 难度
NC53 删除链表的倒数第n个节点 ★☆☆☆☆
NC24 删除有序链表中重复出现的元素 ★★☆☆☆
NC25 删除有序链表中重复的元素 ★★☆☆☆
NC2 重排链表 ★★☆☆☆
NC133 链表的奇偶重排 ★★☆☆☆

2)链表的翻转

  • 对于翻转链表的问题,比较好的做法就是遍历链表,删除遍历到的结点,插到头部,即所谓头插法,只需要实现delNodeinsertNode两个接口即可。时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)
  • 如图所示,先把需要翻转的结点删除,然后插到头部,然后执行下一个结点,直到整个链表遍历完毕,就完成了链表的翻转。
    ❤️大厂面试基础算法总结❤️(强烈推荐)_第3张图片
  • 当然,有些问题可能是选择某一段区间的链表结点进行翻转,方法一样,为了处理头结点的特殊情况,可以在链表头增加一个 “伪头结点”,这样就可以防止链表头随时变化的情况,返回链表头只需要返回"伪头结点" 的 next即可。
题目链接 难度
NC78 反转链表 ★☆☆☆☆
NC50 链表中的节点每k个一组翻转 ★☆☆☆☆
NC40 两个链表生成相加链表 ★☆☆☆☆
NC96 判断一个链表是否为回文结构 ★☆☆☆☆
NC21 链表内指定区间反转 ★★☆☆☆

3)链表的快慢指针

  • 判断一个链表里面有没有环,采用的是快慢指针。总体思路是一个指针走1步,一个指针走2步,由于 1 和 2 互素,如果有环,他们一定会相遇。
    ❤️大厂面试基础算法总结❤️(强烈推荐)_第4张图片
  • 假设没有环的部分,长度为 x x x,环的长度为 y y y,环入口点到相遇点的距离为 z z z,那么慢指针走过的距离为 x + z x+z x+z,快指针走过的距离为 n y + x + z ny + x + z ny+x+z,又知道慢指针速度为1,快指针速度为2,如果它们相遇,则相遇的时间相等,有: ( x + z ) 1 = ( n y + x + z ) 2 \frac {(x+z)} 1 = \frac {(ny+x+z)} 2 1(x+z)=2(ny+x+z)
  • n n n 为任意整数,所以这个方程 z = n y − x z = ny - x z=nyx,这个公式的含义是:慢指针只要再走 x x x 步 就能到达环的入口了。
题目链接 难度
NC66 两个链表的第一个公共结点 ★☆☆☆☆
NC4 判断链表中是否有环 ★★☆☆☆
NC3 链表中环的入口节点 ★★★☆☆

2、双向链表

  • 双向链表比链表本身多了一个指针,指向它的前驱。一般对一些时间复杂度要求较高的问题采用双向链表。
  • 以下两题双向链表的题目,涉及到其它数据结构,较为复杂,建议最后做。
题目链接 难度
NC93 设计LRU缓存结构 ★★★☆☆
NC94 LFU缓存结构设计 ★★★☆☆

3、栈

  • 栈是一种先进后出数据结构,有兴趣的话可以学习下单调栈:夜深人静写算法(十一)- 单调栈。
题目链接 难度
NC76 用两个栈实现队列 ★☆☆☆☆
NC128 容器盛水问题 ★★☆☆☆
NC157 单调栈 ★★☆☆☆
NC108 最大正方形 ★★☆☆☆

4、二叉树

  • 二叉树的遍历有先序、中序、后序、层序;
  • 先序、中序、后序遍历,考察的点主要是递归,一般做题思路是:根据左右子树的遍历结果,来决定当前树的值。子树的结果可以通过返回值返回,也可以通过传参引用返回。
  • 层序遍历就是广度优先搜索了。对于广搜,主要应用是图的最短路问题,如果需要详细学习的话,可以参见以下这篇文章:夜深人静写算法(十)- 单向广搜。
题目链接 难度
NC45 实现二叉树先序,中序和后序遍历 ★☆☆☆☆
NC15 求二叉树的层序遍历 ★☆☆☆☆
NC14 二叉树的之字形层序遍历 ★☆☆☆☆
NC72 二叉树的镜像 ★☆☆☆☆
NC62 平衡二叉树 ★☆☆☆☆
NC13 二叉树的最大深度 ★☆☆☆☆
NC5 二叉树根节点到叶子节点的所有路径和 ★☆☆☆☆
NC8 二叉树根节点到叶子节点和为指定值的路径 ★☆☆☆☆
NC16 判断二叉树是否对称 ★☆☆☆☆
NC6 二叉树的最大路径和 ★☆☆☆☆
NC12 重建二叉树 ★★☆☆☆
NC136 输出二叉树的右视图 ★★☆☆☆
NC60 判断一棵二叉树是否为搜索树 ★★☆☆☆
NC9 二叉树中是否存在节点和 ★★☆☆☆
NC117 合并二叉树 ★★☆☆☆
NC123 序列化二叉树 ★★★☆☆
NC64 二叉搜索树与双向链表 ★★★☆☆

三、算法

1、排序

  • 排序的话,一般面试最喜欢问的是快排,基本大部分技术博客都讲过了,我就不讲了。但是,实际应用中一般用 STL 的 sort配合类重写仿函数就能解决大部分多关键字的排序问题了。
  • 静态的第 k k k 大的数,如果时间复杂度没有太苛刻的要求,基本也都是排个序就解决的事情。
  • 倒是可以用下面的题来练习写一下快排。
题目链接 难度
NC140 排序 ★☆☆☆☆
NC119 最小的K个数 ★☆☆☆☆
NC88 寻找第K大 ★☆☆☆☆
NC33 合并有序链表 ★☆☆☆☆
NC22 合并两个有序的数组 ★☆☆☆☆
NC51 合并k个已排序的链表 ★☆☆☆☆
NC70 链表排序 ★☆☆☆☆
NC97 出现次数的TopK问题 ★☆☆☆☆
NC73 数组中出现次数超过一半的数字 ★☆☆☆☆
NC36 在两个长度相等的排序数组中找到上中位数 ★☆☆☆☆

2、二分枚举

  • 二分查找作为最经典的 O ( l o g 2 n ) O(log_2n) O(log2n) 的算法,也是面试考察的重点,所以手写一个二分查找也是必须的,实际应用中一般用 STL 的 lower_bound就能实现数组的二分查找了。
  • 二分查找不光可以在数组中找数据,还可以对单调函数,二分枚举答案求可行解,例如:求一个数的平方根。
  • 实际上有序数组也是特殊的的单调函数,只不过它的值是离散的。
题目链接 难度
NC105 二分查找 ★☆☆☆☆
NC48 在转动过的有序数组中寻找目标值 ★☆☆☆☆
NC61 两数之和 ★☆☆☆☆
NC54 数组中相加和为0的三元组 ★☆☆☆☆
NC32 求平方根 ★☆☆☆☆
NC86 矩阵元素查找 ★☆☆☆☆
NC29 矩阵查找 ★☆☆☆☆

3、广度优先搜索

题目链接 难度
NC99 树的直径 ★★★☆☆
NC138 矩阵最长递增路径 ★★★☆☆

4、深度优先搜索

  • 深度优先搜索的最大的用处是穷举问题的所有情况,并且进行适当的合法剪枝,所以没有思路的时候可以试着用深搜来求解问题。深搜的实现是递归。
  • 一般枚举全排列、全组合的时候也要用到深搜。
题目链接 难度
NC102 最近公共祖先 ★☆☆☆☆
NC38 螺旋矩阵 ★☆☆☆☆
NC121 字符串的排列 ★☆☆☆☆
NC109 岛屿数量 ★☆☆☆☆
【推荐】NC137 表达式求值 ★★☆☆☆
NC26 括号生成 ★★☆☆☆
NC42 有重复项数字的所有排列 ★★☆☆☆
NC27 集合的所有子集 ★★☆☆☆
NC46 加起来和为目标值的组合 ★★☆☆☆
NC43 没有重复项数字的所有排列 ★★☆☆☆
NC39 N皇后问题 ★★☆☆☆
NC79 丑数 ★★☆☆☆

5、动态规划

  • 这里的动态规划都是最简单的,基本把所有 “简单动态规划” 的内容都涵盖了,这里说一下每一类动态规划的思路。

1)递推

【NC68 跳台阶】一只青蛙一次可以跳上 1 1 1 级台阶,也可以跳上 2 2 2 级。求该青蛙跳上一个 n n n 级的台阶总共有多少种跳法。

  • 递推的问题一般依赖前一项,或者前两项,或者前 c c c 项,且是方案数相加的形式;
  • 对于 n n n 个台阶,我跳 1 1 1 步以后,剩下就是跳 n − 1 n-1 n1 步的情况;跳 2 2 2 步以后,剩下就是跳 n − 2 n-2 n2 步的情况;不能一下子跳 3 3 3 步,所以这个问题的状态转移方程就是: f [ n ] = f [ n − 1 ] + f [ n − 2 ] f[n] = f[n-1] + f[n-2] f[n]=f[n1]+f[n2]

2)子段最优值

【NC19 子数组的最大累加和问题】给定一个数组 a a a,返回子数组的最大累加和,例如, a [ ] = [ 1 , − 2 , 3 , 5 , − 2 , 6 , − 1 ] a[] = [1, -2, 3, 5, -2, 6, -1] a[]=[1,2,3,5,2,6,1],所有子数组中, [ 3 , 5 , − 2 , 6 ] [3, 5, -2, 6] [3,5,2,6] 可以累加出最大的和 12 12 12,所以返回 12 12 12

  • 子段最优值问题,一般是有一个数组序列,要求求一个连续(或非连续)的子序列,运用某种运算达到最优值。
  • 我们一般可以这么设计状态:令 f [ n ] f[n] f[n] 表示以第 n n n 个数结尾能够达到的最优解。
  • 如果要求序列连续,那么 f [ n ] f[n] f[n] 的最优解取决于 f [ n − 1 ] f[n-1] f[n1] 选 和 不选两种情况的最优值。
  • 如果不要求序列连续,那么 f [ n ] f[n] f[n] 的最优解取决于 选 f [ i ] ( i < n ) f[i] (i < n) f[i](i<n) 中的其中一个所达成的最优值。
  • 上面这个问题的状态转移方程(属于连续子段最优值问题)就是: f [ i ] = a [ i ] + { 0 f [ i − 1 ] ≤ 0 f [ i − 1 ] f [ i − 1 ] > 0 f[i] = a[i] + \begin{cases} 0 & f[i-1] \le 0 \\ f[i-1] & f[i-1] > 0\end{cases} f[i]=a[i]+{ 0f[i1]f[i1]0f[i1]>0

3)区间 DP

  • 区间 DP 的状态转移方程如下: d p [ i ] [ j ] = o p t ( d p [ i + 1 ] [ j − 1 ] + c o s t ( i , j ) , d p [ i ] [ k ] + d p [ k + 1 ] [ j ] ) dp[i][j] = opt(dp[i+1][j-1] + cost(i,j), dp[i][k]+dp[k+1][j]) dp[i][j]=opt(dp[i+1][j1]+cost(i,j),dp[i][k]+dp[k+1][j])

4)二维DP

  • 最长公共子序列、最长公共子串、最小编辑距离 都属于二维DP,一般用于两个字符串的匹配问题。
  • 一般的状态转移方程为: d p [ i ] [ j ] = o p t ( d p [ i − 1 ] [ j ] + x , d p [ i ] [ j − 1 ] + y , d p [ i − 1 ] [ j − 1 ] + z ) dp[i][j] = opt(dp[i-1][j]+x, dp[i][j-1]+y, dp[i-1][j-1]+z) dp[i][j]=opt(dp[i1][j]+x,dp[i][j1]+y,dp[i1][j1]+z)
  • 如图所示,比较直观的想法就是,红色位置的状态取决于三个蓝色位置的最优值:
    ❤️大厂面试基础算法总结❤️(强烈推荐)_第5张图片
题目链接 类型
NC68 跳台阶 递推
NC65 斐波那契数列 递推
NC19 子数组的最大累加和问题 子段最优值 - 最大子段和
NC49 最长的括号子串 子段最优值
NC83 子数组最大乘积 子段最优值
NC52 括号序列 区间DP
NC91 最长递增子序列 子段最优值 - 最长递增子序列
NC127 最长公共子串 二维DP - 最长公共子串
NC92 最长公共子序列 二维DP - 最长公共子序列
NC35 最小编辑代价 二维DP - 最小编辑距离
NC59 矩阵的最小路径和 记忆化搜索
NC34 求路径 记忆化搜索
NC87 丢棋子问题 记忆化搜索
NC122 正则表达式匹配 记忆化搜索
NC44 通配符匹配 记忆化搜索
NC17 最长回文子串 区间DP
NC116 把数字翻译成字符串 记忆化搜索
NC126 换钱的最少货币数 0/1 背包

6、贪心

  • 贪心说起来比较微妙,就是穷尽你平生所学来想这样做对不对!就这么简单(难)。
  • 贪心一般配合排序来做。
  • 遇到一些没什么想法的题,可以先排个序,然后看看有什么规律,再来决定用贪心还是动态规划。
题目链接 类型
NC101 缺失数字 ★☆☆☆☆
NC37 合并区间 ★☆☆☆☆
NC95 最长连续子序列 ★☆☆☆☆
NC111 最大数 ★★☆☆☆
NC7 股票(一次交易) ★☆☆☆☆
NC55 最长公共前缀 ★☆☆☆☆
NC132 环形链表的约瑟夫问题 ★☆☆☆☆
NC107 寻找峰值 ★☆☆☆☆
NC110 旋转数组 ★☆☆☆☆
NC134 股票(无限次交易)) ★☆☆☆☆
NC135 股票(两次交易) ★☆☆☆☆
NC130 分糖果问题 ★☆☆☆☆

7、尺取法

  • 尺取法算 ACM 里比较经典的一种解题技巧了,其实就是双指针,左右两个指针,不断推进右指针,然后根据限制条件来推进左指针,每个指针只会往前不会后退,所以时间复杂度是 O ( n ) O(n) O(n) 的。
题目链接 难度
NC41 最长无重复子串 ★☆☆☆☆

8、字符串模拟

题目链接 难度
NC103 反转字符串 ★☆☆☆☆
NC1 大数加法 ★☆☆☆☆
NC141 判断回文 ★☆☆☆☆
NC100 将字符串转化为整数 ★☆☆☆☆
NC20 数字字符串转化成IP地址 ★☆☆☆☆
NC57 反转数字 ★☆☆☆☆
NC89 字符串变形 ★☆☆☆☆
NC113 验证IP地址 ★☆☆☆☆

9、树状数组

  • 放入面试范畴属于较难的数据结构,因为平时也不会去关注这种数据结构,但是如果想学,其实是很简单的,它的特点是:单点更新,成段求和,并且都能在 O ( l o g 2 n ) O(log_2n) O(log2n) 内完成,常数小于线段树,奉上链接:夜深人静写算法(十三)- 树状数组
题目链接 难度
NC90 设计getMin功能的栈 ★★☆☆☆
NC118 数组中的逆序对 ★★☆☆☆
NC131 随时找到数据流的中位数 ★★★☆☆

10、模拟

  • 所谓模拟,就是最直白的跟着题目模拟,题目让你怎么做你就怎么做。
题目链接 难度
NC112 进制转换 ★☆☆☆☆
NC18 顺时针旋转矩阵 ★☆☆☆☆
NC10 大数乘法 ★☆☆☆☆

11、位运算

  • 位运算相关的题一般都比较有意思,尤其是异或。
题目链接 难度
NC75 数组中只出现一次的数字 ★★☆☆☆
NC30 数组中未出现的最小正整数 ★★☆☆☆

你可能感兴趣的:(算法技巧和分析,链表,二叉树,数据结构,算法,动态规划)