【前端校招面经】字节国际化电商前端校招一面凉经

  1. 问 Garfish 框架, 如何处理微前端路由, 以及一大堆框架源码级细节问题
  2. 微前端中, 切换多种不同子工程, 与同一子工程内部切换路由有哪些区别
  3. 微前端中, iframe 元素特点, iframe 能否操作主页面 DOM 节点, 能否获取主页面 cookie
  4. React, 讲一讲自定义 hook
  5. 讲一讲 TCP 三次握手, 第三次握手发送方是否可以携带信息
  6. 讲一讲进程, 线程, 协程三者区别
  7. 程序执行的原理, 当 CPU 执行程序, 读取变量时, 变量存储在内存, 三级缓存和寄存器中有哪些区别
  8. 为什么在 js 中0.1 + 0.2 !== 0.3, 名词解释什么叫定点浮点, js 存储数字和 C 语言有什么区别?
  9. number 类型表示整数的最大范围
  10. 手撕算法: 传入一个这样的数据结构
[
  { 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)));
  1. 手撕算法: 传入一个正整数 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]
#前端##面经##校招##字节跳动##前端工程师#
全部评论
第10题楼主会做吗?
1 回复
分享
发布于 2022-02-10 10:14
第一道算法题 ```     function t10(arr) {         const arr1 = []         arr.forEach(item => {             arr1.push({id: item.id, children: []})         })         for (let i = arr.length-1; i >=0; i--) {             if (arr[i].parentId!==null){                 let item=arr1.pop()                 arr1[arr[i].parentId-1].children.push(item)             }         }         return arr1     } ```
1 回复
分享
发布于 2022-03-22 21:40
乐元素
校招火热招聘中
官网直投
请问你是什么时候面的 然后什么时候给你发感谢信呢
点赞 回复
分享
发布于 2021-10-09 19:24
就**离谱
点赞 回复
分享
发布于 2021-10-09 19:44
怎么感觉问的这么难
点赞 回复
分享
发布于 2021-10-11 10:56
在字节实习过吗 怎么还用过garfish
点赞 回复
分享
发布于 2021-10-13 12:53
数组转树形结构 楼主写的好复杂的感觉
点赞 回复
分享
发布于 2022-02-15 14:12
楼主,你是在简历上写了做微前端的吗
点赞 回复
分享
发布于 2022-02-22 09:43
这么难,难怪我简历筛选就直接挂了。😅
点赞 回复
分享
发布于 2022-03-23 13:26
校友啊,你这个一面问的算难的了,最后去哪了?
点赞 回复
分享
发布于 2022-03-23 13:41
请问面的base是上海吗
点赞 回复
分享
发布于 2022-04-15 18:50

相关推荐

9 71 评论
分享
牛客网
牛客企业服务