【前端面试题】字节常考算法笔试题(面试必看)
树类型题目
-
树的遍历,前序:根左右 中序:左根右 后序:左右根 (leetcode144、leetcode94、leetcode145)
-
广度优先遍历 leetcode102. 二叉树的层序遍历
-
leetcode199. 二叉树的右视图. 右视图.核心是记下来 每层的最后一个元素,多加一个 while.
-
leetcode257. 二叉树的所有路径.核心是第一个元素记下来。 总之是内部套一个 while 进行记录当前层的个数。
-
leetcode104. 二叉树的最大深度给定一个二叉树,找出其最大深度。 核心是递归 Math.max( maxDepth(root.left), maxDepth(root.right) )+1;
-
leetcode257. 二叉树的所有路径。 给一个树 找出所有的路径(递归方法找到所有的可能); 核心是递归的 出去条件左右为空, 依次左右的进栈
-
leetcode101. 110. 平衡二叉树。 给定一个二叉树,判断它是否是高度平衡的二叉树。 核心是:左右都是平衡的 and 左右的深度差<=1
-
leetcode543 核心是:求高度的时候,顺便记一下左右的宽度就可以了。 给定一棵二叉树,你需要计算它的直径长度。 一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。 getDepth(root.left)+getDepth(root.right)+1. 顺便记一下最大的值
-
leetcode958. 二叉树的完全性检验。给定一个二叉树的 root ,确定它是否是一个 完全二叉树。 核心是:按层遍历(BFS) 是 null 也要进去,遍历的时候 null 表示结束了。如果后边还有数字说明并非是完全二叉树。
-
leetcode199. 二叉树的右视图 BFS
-
leetcode637. 二叉树的层平均值 BFS
-
leetcode114. 二叉树展开为链表 前序遍历放到栈中。然后依次修改后边的指向。
-
leetcode236. 二叉树的最近公共祖先
-
leetcode124. 二叉树中的最大路径和。 这个题与求直径宽度的方法是一模一样的。 直接获得深度就好了。
-
leetcode1302. 层数最深叶子节点的和。 依然是按照深度遍历,然后将节点保存在 map 中,获得最大值后,从 map 中取出与最大的值相同的一层数据。
-
求根到叶子的所有和 , 每层前 10
-
求根到 叶的节点的值 是否存在某个和。
-
求根到 叶的节点的值 存在某个和的路径。
-
求 根 到 叶的节点的路径上的所有和。
-
头条. 给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点
-
算法题:一开始问的是一棵树里最远的两个节点间的距离,思考的有点久于是换题了... [543. 二叉树的直径] 核心是 depPath 递归计算
-
算法题目: 二叉树最小公共祖先[leetcode235. 二叉搜索树的最近公共祖先] 这个是个搜索树,关键是和 root 节点相比较。
-
求二叉树中两个节点之间的最大距离。 核心方法: 深度的时候记录下宽度。
-
leetcode124. 二叉树中的最大路径和. 核心方法: 这个是递归,注意最小的值,不能是负数的,这就保证了,如果为负不处理一侧的数据。
-
leetcode543 10.任意一颗二叉树,求最大节点距离 //. 二叉树的直径, 核心就是:递归,求的左子树/右子树+1
回文类题目
- leet125. 验证回文串。 判断字符串是否为回文 核心是队列,注意队列中应该留有的一个长度。 不断的进队列,然后两端比较队列,查看最终剩余的元素个数,>1 则非回文。
- leetcode5 最长回文子串。 给你一个字符串 s,找到 s 中最长的回文子串。. 【绘制 0,1 dp*2 矩阵,标记右上矩阵列表,求得最长的 l,然后将区间返回。 填充形状为从对角线向右上角】
- leetcode647. 【和最长回文子串一样的, 先标记矩阵, 然后统计矩阵的值为 1 的个数】,回文子串。 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
- leetcode516. 最长回文子序列。给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。 子序列不要求是连续的。
- 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 【默认】
// 示例 1:输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。
// 示例 2:输入: "cbbd" 输出: "bb"
// `https://leetcode-cn.com/problems/longest-palindromic-substring/submissions/`
// 核心方法,还是 dp 矩阵。
- leetcode 44. 通配符匹配 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '' 的通配符匹配。
// 核心方法: 构建 dp 矩阵[多一个], 然后遇到 则从 正下 1 后全部通吃, ? 则斜下一个 1, 如果是字符则去比较,如果相同为 1。 是两个 for 嵌套
//https://leetcode-cn.com/problems/wildcard-matching/
排序类题目
- BubbleSort 冒泡排序: 比较相邻的元素。如果第一个比第二个大,就交换他们两个. 一次下来找到一个最大的。
- SelectionSort 选择排序: 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- insertionSort 插入排序: 类似于打扑克牌,分为两个有序队列 和 待排的序列,从待排中一次找到位置
- shellSort 希尔排序; 核心是定长分组排序. 3 个 for 1 个 if. 核心在第三个 for 其实是逐步的放大,从而整体有序。
- Merge Sort 归并排序: 一定是两个一个拆分,一个合并.
- Quick Sort 快速排序: 移动内部使得左边的都比 pivot 小,右边的都比它大。 并且返回基准的位置
- 归并排序完成二维数组合并。 这个题很不错,稍微变动了点,但是整体的思想没变。 就在合并的地方
骚操作.. [[1,2,3],[4,5,6],[7,8,9],[1,2,3],[4,5,6]].flat(Infinity).sort((a,b)=>{ return a-b;})
字符串、数组类题目
-
无重复字符的最长子串 leetcode3. 核心方法是: 找到字符串中的最长串 滑动窗口的解法
-
判断数组中是否包含和为 sum 的 n 个数子序列。 leetcode 的题目没有找到,这里用了求不重复的子集的方法,把所有的子集都求出来。
头条. 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
核心方法: 找到到 pre 的最大的连续的值(要么与前面+,要不用自己) -
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。 示例:
给定nums = [2, 7, 11, 15]
,target = 9
因为nums[0] + nums[1] = 2 + 7 = 9
-
用 JavaScript 写一个函数,输入 int 型,返回整数逆序后的字符串。
如:输入整型 1234,返回字符串“4321”。要求必须使用递归函数调用,不能用全局变量,输入函数必须只有一个参数传入,必须返回字符串。 -
实现一个字符串匹配算法,从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置。 #119 【这个看看就好了】
-
打印出 1 - 10000 之间的所有对称数 例如 121、1331 等
-
算法题: 有一个无序数组求中位数
//中位数是指将一个无序数组排成有序之后,位置为(n+1)/2 的元素。 (还可以使用二分法) -
(美团)在从左向右和从上往下皆为升序的二维数组中,查找一个数是否存在,存在的话输出它的位置 leetcode74. 搜索二维矩阵 核心方法: 从左下角开始遍历。看看能否找到对应的元素 如果到了右上角还是没有,则说明不在其中。
-
算法题:最长不重复字串。 核心方法: 利用滑动窗口的机制,如果下一个在里面则 splice,否则 push。计算长度。
-
乘积最大子数组. leetcode152. 核心方法: 使用类似股票的双队列记录最大值和最小值,但是不是取的最后,是取得最大列的其中最大值。(股票取最后因为股票是最后一天)
-
车队的问题 leetcode 853. 说明 题目文字理解挺复杂,应该不会面到。
-
最接近的三数之和. 输出数组中任意三个数相加与输入数字最接近的数 leetcode16 核心方法:【排序,for 占一个位置,然后 left 和 right 剩下的逼近】
样例 .输入:test1([-1,2,1,-4], 1) 输出:2 -
输出数组中不重复的元素。 直接 map 方法
样例 输入:test2([1,2,1,3,2,5]) 输出:[3, 5] -
回行矩阵遍历 核心方法:细心就好了
-
找到一个具有最大和的连续子数组(返回其和) 说明: 这个其实也是 n*1 的矩阵,前面的状态转移方式 self or (self+before)
-
剑指 Offer 29. 顺时针打印矩阵
-
买卖股票的最佳时机 II leetcode 122 核心方法:【多次买卖,用 dp 持有或者不持有】 使用状态矩阵
-
买卖股票的最佳时机 I leetcode 121 核心方法:【找到最低的,只要后边有比他高的就计算求 maxGain】
-
数组中和的最短子数组长度。 leetcode862. 和至少为 K 的最短子数组 核心方法[必然逃不过 dp 矩阵,计算从 i 到 j 的和填充矩阵,找到直接 return]
-
二维数组中,只能向右和向下,找到从左上角到右下角路径中和最大的值 //leet62. 不同路径. DP 矩阵,先填充第一行/第一列。其他的求的最值。
-
笔试题:求连续子数组的最大和 leetcode 剑指 Offer 42. 连续子数组的最大和. 核心方法: 记录下前的最大值。
-
leet46. 全排列.给定一个 没有重复 数字的序列,返回其所有可能的全排列。 核心方法:递归调用即可,注意返回的值是一个数组。
-
一个数组,去掉相邻元素的重复值,保留一个重复值.示例:输入 [1,3,5,5,5,3,4,6,6,7,4] 输出[1,3,5,3,4,6,7,4]
-
删除字符串中的所有相邻重复项 leetcode 1047 核心方法:这种问题就是利用栈处理。
-
删除字符串中的所有相邻重复项 II (关键是双栈,单的会超时) leetcode 1209. 核心方法: 利用双栈, 一个栈存当前数字,一个存对应的个数
-
递增的三元子序列。 leetcode 334. 核心方法: map 按序记录前面比自己小的数据,然后取的最大的加 1. 使用 map + 双循环 的方法解决。
-
剑指 Offer II 081. 允许重复选择元素的组合. https://leetcode-cn.com/problems/Ygoe9J/
// -- candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是不同的。 -
剑指 Offer II 082. 含有重复元素集合的组合. https://leetcode-cn.com/problems/4sjJUc/
// --注意条件是: candidates 中的每个数字在每个组合中只能使用一次, 解集不能包含重复的组合。 [只是多了一个剪枝条件] -
剑指 Offer II 083. 没有重复元素集合的全排列 https://leetcode-cn.com/problems/VvJkup/
-
剑指 Offer II 084. 含有重复元素集合的全排列 https://leetcode-cn.com/problems/7p8L0Z/submissions/
//给定一个可包含重复数字的整数集合 nums ,按任意顺序 返回它所有不重复的全排列。 [使用一个 set 记录下 某个元素是否被当作头部] -
leetcode 78.子集 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。(互不相同)
-
leetcode 90. 子集 II(包含相同的) 给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
-
重复的子字符串. https://leetcode-cn.com/problems/repeated-substring-pattern/
// 使用正则方法 return /^([a-z]+)\1+$/.test(s)
// 或者是使用 遍历 n,然后使用 repeat 的方法. -
剑指 Offer II 016. 不含重复字符的最长子字符串 https://leetcode-cn.com/problems/wtcaE1/
// 用滑块的方法解决。 可以单独申请一个栈,然后不断的向里面 push,并切割出来。
下面是 KS 面试题
-
两个大数相加 ,要求显示相加的结果. 核心方法:大数相加,直接使用逆序为数组逐项相加。
-
leetcode 20. 有效的括号. 用的是栈的方式。
-
给定一个整数数组 ,其中有些元素出现两次而其他元素出现一次。找到所有出现两次的元素。
示例:输入: [4,3,2,7,8,2,3,1] 输出: [2,3] -
在一个整数的数组中,找到两个数的和等于某个数,返回这两个数的下标 [使用了 map,小米的面试中遇到了]
-
判断是否括号是否合法,有三种括号() [] {}
-
给定一个字符串,找出最长的一个子串,其中没有重复的字符
-
给定一个数组,包括 0,1,2 三种数组,原地排序,一遍走完。 核心方法:前后指针的方法
-
给定一个表达式字符串,包括数字和操作符,给这个表达式添加括号,改变运算顺序,得到不同的结果,算出总共有多少种结果。 (不处理)
-
给定一个字符串,包含'('和')',找出最长的括号合法的子串 [没有找到]
-
leetcode 剑指 Offer II 085. 生成匹配的括号 //https://leetcode-cn.com/problems/IDBivT/
-
给定一个数组形式的表达式,给出这个表达式的逆波兰表达式,输出为数组。表达式中可能包括括号,结果中要去除括号
-
逆波兰表达式求值 (关键是负数的取整问题)
// https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/ -
给定一个字符串 S 和一个字符串 T,找到 S 中最小的子串,包括 T 中的所有字符,需要在线性时间内完成。[困难的]
// 最小覆盖子串https://leetcode-cn.com/problems/minimum-window-substring/
// 增加窗口右边界,寻找一个可行解,在找到可行解的情况下增加窗口左边界,优化可行解,找到最优解 -
给定一个数组,返回一个新数组。新数组中 counts[i]表示 num[i]右侧有多少个数字比 nums[i]小 [困难的]
// leetcode 315. 计算右侧小于当前元素的个数 https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self/ -
连续子数组的最大和. //MomntA 考了,核心方法:动态规划,要不取,要不我不取不断的变换方法
// 剑指 Offer 42. 连续子数组的最大和. https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/ -
求出最小的 k 个数. //核心方法 可以使用二分也可以使用比较笨的。
// 剑指 Offer 40. 最小的 k 个数. https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/submissions/ -
0/1 背包问题、部分背包问题 【动态规划问题】
-
leetcode 322. 零钱兑换 https://leetcode-cn.com/problems/coin-change/submissions/
// 一个一个的填充重量,获得状态转移方程,最终求得最后的解。 遍历 amout, 和 coin,看看当前金币能否放下,可以的话,取的他前面的值。 -
数据流中的中位数 【还未处理,感觉不会考,用的是大小顶锥】
// https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/ -
剑指 Offer 11. 旋转数组的最小数字
// https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/
// 注意这个地方,其实有个相等的,相等的时候不能去给 mid 赋值。 -
搜索旋转排序数组(指定某个数是否在里面) leetcode 33. //核心方法: 判断 mid 和 target 的关系. 小抄
// https://leetcode-cn.com/problems/search-in-rotated-sorted-array/ -
单词距离 (leetcode 面试题 17.11.) 核心方法:[遍历出来所有的位置。保存在两个数组中,然后比较 0 位置的大小,不断的进栈和出栈]
// https://leetcode-cn.com/problems/find-closest-lcci/ -
连续最大子串和 (面试题) 核心放: 关键是 dp 算法,加上前面 或者 是取本身
-
1 比特与 2 比特字符 核心方法:(关键题意是字符是合法的, 要求最后一位是一个单独合法的字符。 因此:核心是队列遇 1 出对,遇 0 出 1 个)
// https://leetcode-cn.com/problems/1-bit-and-2-bit-characters/ -
复原 IP 地址 (leetcode. 93) 核心方法:(递归剪取,然后判断 IP) 自己一遍过,类似于括号剪枝方法。
// https://leetcode-cn.com/problems/restore-ip-addresses/ -
最小覆盖子串 leetcode 76 核心方法:用于使用 i,j 两端指针,左移右移的方法。 自己写的超时了,还有优化的空间。
//https://leetcode-cn.com/problems/minimum-window-substring/ -
盛最多水的容器 leetcode 11 核心方法: 还是双端的指针,下次容器的边界不会是高度最小的。
//https://leetcode-cn.com/problems/container-with-most-water/ -
字典序的第 K 小数字 leetcode440. 给定整数 n 和 k,返回 [1, n] 中字典序第 k 小的数字。 说明: 自己写了不过超时了
//https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order/ -
基本计算器 leetcode.224 hard 类型
//https://leetcode-cn.com/problems/basic-calculator/ -
最短无序连续子数组 leetcode 581. 核心方法从前往后找比前面最大的要小的最后一个数,同理另外一个相反。
//https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/ -
颜色分类 leetcode 75. 三种数字原地排序. 核心方法: p0,p1 指向[0,1]结束位置. 如果是 1 这换 p1。 如果是 0 则换两次。
// https://leetcode-cn.com/problems/sort-colors/ -
移除元素 leetcode 27. 从数组中移除某个值为 x 的元素. 核心方法:开始指针,是颜色分类的低级版本。
-
24 点游戏 leetcode 649. hard 类型的。
//https://leetcode-cn.com/problems/24-game/solution/24-dian-you-xi-by-leetcode-solution/ -
最小栈 leetcode 155 核心方法: 建立另外一个数组,时刻都保存当前的最小值。同样的跟随主栈进出栈。
//https://leetcode-cn.com/problems/min-stack/ -
面试题 08.05. 递归乘法 核心方法: 使用位移的方式
//https://leetcode-cn.com/problems/recursive-mulitply-lcci/ -
组合总和 II. leetcode 40. 核心方法是 dfs. 递归方法获得【第一遍就做出来了】
//https://leetcode-cn.com/problems/combination-sum-ii/ -
有效三角形的个数 leetcode 611. 给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。 [小抄了]
//https://leetcode-cn.com/problems/valid-triangle-number/
链表问题
链表的核心是 记得怎么转换即可。
-
链表的反转, 简单一个 pre 搞定 leetcode206. 反转链表.
-
奇偶链表 leetcode328. 奇偶链表
-
怎么获取相交链表的第一个相交点? 核心方法:这个核心其实链表对换下进行向后走。 题目中明确告知了相交求交点。
-
算法题:链表成环判断 [快慢指针]
-
算法题:链表交叉判断 [查看最后一个元素是否相同]
-
面试题 02.07. 链表相交: 它们总有一次回相同的,只要判断好 NodeA 和 NodeB 即可
-
两个栈实现队列 //leetcode 剑指 Offer 09. 用两个栈实现队列。 没啥可难的。
-
单链表排序 //leetcode148. 核心方法:排序链表 使用冒泡排序的方法。
-
删除链表的倒数第 N 个结点. //leetcode19 注意这里有个坑那就是 n 恰好和长度一样。
-
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
// 示例 1:输入:1->2->4, 1->3→4 输出:1->1->2->3->4->4
// https://leetcode-cn.com/problems/merge-two-sorted-lists/ -
判断两个链表是否相交,如果相交如何快速求出两个链表中的第一个公共节点 //核心方法: 到尾后切换链表遍历
// https://leetcode-cn.com/problems/intersection-of-two-linked-lists/submissions/ -
排序链表 leetcode 148, 核心方法: 可以使用冒泡排序,交换相邻的位置
// https://leetcode-cn.com/problems/sort-list/
查找系列问题
- 实现二分查找的方法
其他未知系列问题
-
请分别用深度优先思想和广度优先思想实现一个拷贝函数? (这种操作。。)
-
(阿里巴巴)快速排序
-
(阿里巴巴)反转链表
-
LRU cache (头条、蚂蚁) 这个问题不大
-
二叉树层次遍历(头条)、这个题目之前也讲过,114. 二叉树展开为链表 中序遍历
-
二叉树寻找最近公共父节点(快手) Leetcode.236 二叉树的最近公共父亲节点 236. 二叉树的最近公共祖先[我用了遍历所有的路径,取得路径的相同值,注意路径相同的时候]
-
数据流的中位数 [这个题没做,简单的办法就是排序,取得中位数] leetcode295. 数据流的中位数 【hard 类型,感觉不会考】
-
算法题 1:给定数组,快速求出所有数右边第一个比其大的数。回答思路
-
算法题 2:给定 k 个数组,每个数组都是有序的,且每个数组最大值-最小值<1000,1<k<1000,求所有数的中位数。回答思路 [log(m+n)]的方法
-
一棵树上路径和为固定值的那些路径 [核心是递归]
-
归并排序 [问题不大]
-
两个栈实现一个队列、怎么优化
-
数组每一个元素找出数组右边第一个大于自己的数. 关键是进栈的是 idnex
-
实现 LRU leetcode146. LRU 缓存机制. 关键是 Map 方法的使用
-
实现一个排序树,能插入,能删除,能平衡
-
输入一个数组,要求输出数组中每个数字后面第一个比他大的数字,没有比他大的输出-1,时间复杂度 O(n)。输入:5,1,9,6,7 输出:9,9,-1,7,-1
-
手写题:在线编程,getUrlParams(url,key); 就是很简单的获取 url 的某个参数的问题,但要考虑边界情况,多个返回值等等
//这个地方栽了一次大坑【字节加面】 //总结 思路有的当时不该用箭头函数,同时要保持清醒,不要听面试官一直说。
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
// add(1)(2)(3) = 6;
// add(1, 2, 3)(4) = 10;
// add(1)(2)(3)(4)(5) = 15;
function add(...rest){
const parms = [...rest]
let add = function(...others){
parms.push(...others);
return add;
}
add.toString = function(){
return parms.reduce((item, acc)=> acc+item);
}
return add;
console.log(add(1)(2)(3));
console.log(add(1, 2, 3)(4));
console.log(add(1)(2)(3)(4)(5));