返回

前端笔试题的独特解法:深入剖析巧妙思路

前端

前端笔试中,一道考察我们基本功和临场发挥能力的题目引起了我的兴趣,原作者给出了一个颇为巧妙的解法,着实令人赞叹。而今,在拥有充裕思考时间的前提下,本文将尝试从多个角度对这道题进行深入剖析,以期从中汲取更丰富的知识和经验。

首先,我们来看看这道题目:

题目:
给定一个字符串,要求将其中所有连续出现的重复字符压缩为单个字符。

示例:

  • 输入:"aabbbcccaaa"
  • 输出:"abca"

这道题看似简单,但要临场发挥出如此巧妙的解法绝非易事。原作者的解法如下:

function compressString(s) {
  let compressed = "";
  let count = 1;
  for (let i = 0; i < s.length; i++) {
    if (s[i] === s[i + 1]) count++;
    else {
      compressed += s[i] + count.toString();
      count = 1;
    }
  }
  return compressed.length < s.length ? compressed : s;
}

这个解法巧妙地利用了 JavaScript 字符串连接的特性,将字符和计数拼接在一起。通过遍历字符串,并在遇到连续重复字符时累加计数,最终得到压缩后的字符串。

为了进一步理解这个解法,我们不妨来手动模拟一下压缩过程:

  • 遍历字符串 "aabbbcccaaa",遇到第一个字符 'a',计数为 1。
  • 遇到第二个 'a',计数加 1,变为 2。
  • 遇到第三个 'a',计数再加 1,变为 3。
  • 此时遇到不同的字符 'b',将 'a' 和计数 '3' 拼接,得到 "a3"。
  • 重置计数为 1,继续遍历,依次压缩 "b"、"c" 等字符。
  • 最终得到压缩后的字符串 "a3b1c3a3"。

通过这个模拟过程,我们可以看到解法的核心在于字符和计数的拼接,以及在遇到不同字符时及时重置计数。这种思路不仅巧妙,而且在代码实现上也简洁易懂。

除了原作者给出的解法,本文还尝试探索其他可能的解法。例如,我们可以使用正则表达式来匹配连续重复的字符,然后用替换操作进行压缩:

function compressString(s) {
  let compressed = s.replace(/(\w)\1+/g, "$1$+{count.length}");
  return compressed.length < s.length ? compressed : s;
}

这个解法利用了正则表达式中的贪婪匹配,可以一次性匹配所有连续重复的字符。不过,需要注意的是,这个解法在某些情况下可能无法正确压缩字符串,例如当计数超过 9 时。

此外,我们还可以使用栈数据结构来实现压缩:

function compressString(s) {
  let stack = [];
  for (let i = 0; i < s.length; i++) {
    if (stack.length > 0 && stack[stack.length - 1].char === s[i]) {
      stack[stack.length - 1].count++;
    } else {
      stack.push({ char: s[i], count: 1 });
    }
  }
  let compressed = "";
  while (stack.length > 0) {
    compressed += stack.pop().char + stack.pop().count.toString();
  }
  return compressed;
}

这个解法使用栈来记录连续重复的字符及其计数,最终通过出栈操作将压缩后的字符串拼接起来。这个解法的优势在于代码逻辑清晰,而且可以正确处理计数超过 9 的情况。

通过对这道笔试题的深入剖析,我们不仅学习了原作者巧妙的解法,还探索了其他可行的解法。在面试准备和技术提升的过程中,这种多角度思考和实践探索的方式无疑是极有价值的。