做一下两道钉钉的笔试题

170 阅读3分钟

看到一篇文章,5年前端面经,里面有两道钉钉的笔试题,所以来做一遍。

笔试题 1:失败重试机制

需求:实现一个函数,对某个异步操作进行重试。首次失败后等待 200ms 重试,若再次失败则等待 500ms 重试,若仍失败则返回最终失败。

分析下解决的步骤:

  1. 尝试执行任务,如果成功则返回结果。

  2. 如果失败,等待200ms后再次尝试。

  3. 如果再次失败,等待500ms后第三次尝试。

  4. 如果第三次失败,抛出错误或返回失败。

ok, 有了步骤实现起来就很方便了。

实现代码

/**
 * 带延迟的重试机制
 * @param {Function} task - 需要重试的异步任务(返回 Promise)
 * @returns {Promise} - 最终结果或失败
 */
async function withRetry(task) {
  const delays = [200, 500]; // 重试延迟时间(单位:毫秒)
  let attempt = 0; // 当前重试次数

  while (true) {
    try {
      return await task(); // 执行任务,成功则直接返回,这里必须使用await,因为 trycatch 不能捕获异步。
    } catch (error) {
      // 判断是否重试次数用尽,如果用尽抛出错误
      if (attempt >= delays.length) {
        throw new Error('重试结束了');
      }
      // 获取当前重试的延迟时间
      const delay = delays[attempt];
      console.log(`第 ${attempt + 1} 次重试,等待 ${delay}ms`);
      // 等延迟时间结束之后,进行下一次循环,(sleep函数)
      await new Promise(resolve => setTimeout(resolve, delay)); // 等待延迟
      attempt++;
    }
  }
}

// 模拟一个可能失败,可能成功的操作
const mockTask = () => {
  return new Promise((resolve, reject) => {
    const isSuccess = Math.random() < 0.2; // 20% 成功率
    isSuccess ? resolve("成功!") : reject("失败!");
  });
};

withRetry(mockTask)
  .then(res => console.log("结果:", res))
  .catch(err => console.error("最终失败:", err));

image.png

笔试题 2:查找连续重复字符

需求:找出字符串中连续重复次数最多的字符,并返回该字符、起始位置和结束位置。

分析:

  1. 首先初始化变量,记录最多重复的字符,最多重复的字符的次数,最多重复字符的起点位置和终点位置,当前遍历的字符,当前遍历的起始位置,当前遍历字符的次数。一共七个变量。
  2. 遍历字符串,判断当前遍历的字符和最多重复的字符是否一致,
    • 如果相同,当前重复的字符的次数+1;

    • 如果不同:

      • 检查当前字符的连续次数是否超过了 maxCount,如果超过,就更新 maxCharmaxCountstartIdx 和 endIdx
      • 更新 currentChar 为当前字符,currentCount 重置为 1,currentStartIdx 更新为当前位置。

实现代码


function findMaxRepeatedCharacter(str) {
  // 初始化变量
  let maxChar = '';
  let maxCount = 0;
  let startIdx = -1;
  let endIdx = -1;

  let currentChar = '';
  let currentCount = 0;
  let currentStartIdx = 0;

  // 遍历字符串
  for (let i = 0; i < str.length; i++) {
    // 检查当前字符是否与前一个字符相同
    if (str[i] === currentChar) {
      currentCount++; // 如果相同,计数器加一
    } else {
      // 如果遇到不同的字符,检查之前的连续字符是否是最大的
      if (currentCount > maxCount) {
        maxChar = currentChar;
        maxCount = currentCount;
        startIdx = currentStartIdx;
        endIdx = i - 1;
      }
      // 更新当前字符
      currentChar = str[i];
      currentCount = 1;
      currentStartIdx = i;
    }
  }

  // 最后检查一次循环结束后的字符(防止字符串以相同字符结尾),
  // 比如‘aaabbbbb’字符串,最后一次遍历没有走else,max未被重新赋值。
  if (currentCount > maxCount) {
    maxChar = currentChar;
    maxCount = currentCount;
    startIdx = currentStartIdx;
    endIdx = str.length - 1;
  }

  return { char: maxChar, start: startIdx, end: endIdx };
}

// 测试
const result = findMaxRepeatedCharacter("aaabbccccddeeee");
console.log(result);  // { char: 'e', start: 12, end: 15 }