【前端校招面经】字节国际化电商前端校招一面凉经
- 问 Garfish 框架, 如何处理微前端路由, 以及一大堆框架源码级细节问题
- 微前端中, 切换多种不同子工程, 与同一子工程内部切换路由有哪些区别
- 微前端中, iframe 元素特点, iframe 能否操作主页面 DOM 节点, 能否获取主页面 cookie
- React, 讲一讲自定义 hook
- 讲一讲 TCP 三次握手, 第三次握手发送方是否可以携带信息
- 讲一讲进程, 线程, 协程三者区别
- 程序执行的原理, 当 CPU 执行程序, 读取变量时, 变量存储在内存, 三级缓存和寄存器中有哪些区别
- 为什么在 js 中
0.1 + 0.2 !== 0.3
, 名词解释什么叫定点
和浮点
, js 存储数字和 C 语言有什么区别? - number 类型表示整数的最大范围
- 手撕算法: 传入一个这样的数据结构
[ { id: 1, parentId: null }, { id: 2, parentId: 1 }, { id: 3, parentId: 1 }, { id: 4, parentId: 2 }, { id: 5, parentId: 2 }, { id: 6, parentId: 3 } ]
输出如下结果:
{ id: 1, children: [ { id: 2, children: [ { id: 4, children: [] }, { id: 5, children: [] } ] }, { id: 3, children: [ { id: 6, children: [] } ] } ] }
在给定的数据中确定根节点, 然后从根节点开始递归构建节点即可
解法如下:
type NodeData = { id: number, parentId: null | number }; type TreeNode = { id: number, children: TreeNode[] }; const data: NodeData[] = [ { id: 1, parentId: null }, { id: 2, parentId: 1 }, { id: 3, parentId: 1 }, { id: 4, parentId: 2 }, { id: 5, parentId: 2 }, { id: 6, parentId: 3 } ]; function createNode(id: number, data: NodeData[]): TreeNode { // 去 data 中查找这个构建的 node 有哪些子节点 const childData = data.filter(({ parentId }) => parentId === id); const node: TreeNode = { id, children: childData.reduce((acc, cur) => { acc.push(createNode(cur.id, data)); return acc; }, []) }; return node; } function getTree(data: NodeData[]): TreeNode { // 先获取到哪个是根节点 const rootNodeData = data.find(({ parentId }) => parentId === null); if (!rootNodeData) { throw new Error('在给定的数据中找不到根节点'); } // 从根节点开始构建节点, 递归构建成树 return createNode(rootNodeData.id, data); } console.log(JSON.stringify(getTree(data)));
- 手撕算法: 传入一个正整数 n, 输出一个"内卷"形输出, 如
- 输入 1, 输出:
1
- 输入 2, 输出:
1, 2
4, 3
- 输入 3, 输出:
1, 2, 3
8, 9, 4
7, 6, 5
- 输入 4, 输出:
1, 2, 3, 4
12, 13, 14, 5
11, 16, 15, 6
10, 9, 8, 7
- 输入 5, 输出:
1, 2, 3, 4, 5
16, 17, 18, 19, 6
15, 24, 25, 20, 7
14, 23, 22, 21, 8
13, 12, 11, 10, 9
思路:
将每一次绕行一周的行为抽象出函数, 循环执行
如 n = 5 时, 先构建最外层一圈 1,2,3,4,5 -> 6,7,8,9 -> 10,11,12,13 -> 14,15,16
再构建内部一层 17,18,19... 直到最中心一层 25
解法:
/** * 生成顺时针添加数字的矩阵 * @param num 用户输入的数字 * @returns result */ function getClockwiseMatrix(num: number): number[] | number[][] { if (num <= 0) { throw new Error('提供的 num 必须要是一个正数'); } if (num === 1) { return [1]; } // 构建空 result, 准备往里面添加值 const matrix = initMutiMatrix(num); // 开始顺时针绕行构建矩阵 let curNum = 1, count = num; for (let i = 0; i < Math.ceil(num / 2); i++) { curNum = addNumberToMatrix(curNum, i, i, count, matrix); count -= 2; } return matrix; } /** * 生成初始化 n 行 n 列矩阵 * @param num 用户输入的值 * @returns 如用户输入 3, 则返回[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] */ function initMutiMatrix(num: number): number[][] { // 构建空 result, 准备往里面添加值 const matrix: number[][] = []; const addRow = (num: number): number[] => { const row: number[] = []; for (let i = 0; i < num; i++) { row.push(0); } return row; } for (let i = 0; i < num; i++) { matrix.push(addRow(num)); } return matrix; }; /** * 从 matrix[i][j] 位置开始, 顺时针绕行一周向矩阵内添加值 * @param num 绕行一周起始值 * @param i 绕行起始位置的横坐标 * @param j 绕行起始位置的纵坐标 * @param count 绕行一周遍历 4 次, 每一次遍历的数量 * @param matrix 矩阵数据 * @returns 绕行一周结束后, 下一次绕行的起始值, 作为下一次调用该函数的 num 值 */ function addNumberToMatrix(num: number, i: number, j: number, count: number, matrix: number[][]): number { // 如果 count 为 1, 说明是执行到了最后, 向矩阵最中心位置添加一个数字即可 if (count === 1) { matrix[i][j] = num; return num + 1; } let _i = i, _j = j, _num = num; // 顺时针添加数字: 从左到右 for (let k = 0; k < count; k++) { matrix[_i][_j] = _num; if (k + 1 < count) { _num++; _j++; } } // 顺时针添加数字: 从上到下 for (let k = 0; k < count; k++) { matrix[_i][_j] = _num; if (k + 1 < count) { _num++; _i++; } } // 顺时针添加数字: 从右到左 for (let k = 0; k < count; k++) { matrix[_i][_j] = _num; if (k + 1 < count) { _num++; _j--; } } // 顺时针添加数字: 从下到上(最后一步需特殊处理) for (let k = 0; k < count - 1; k++) { matrix[_i][_j] = _num; _num++; _i--; } return _num; } /** * 按要求打印目标矩阵 */ function renderMatrix(matrix: number[][] | number[]) { if (matrix.length === 1) { console.log(JSON.stringify(matrix)); return; } matrix.forEach(row => { console.log(JSON.stringify(row)); }); } //test: const result = getClockwiseMatrix(5); renderMatrix(result); // --> result: // [1,2,3,4,5] // [16,17,18,19,6] // [15,24,25,20,7] // [14,23,22,21,8] // [13,12,11,10,9]#前端##面经##校招##字节跳动##前端工程师#