Skip to content

根据运算优先级添加括号

Posted on:2023年3月4日 at 22:54

现已知一个字符串是由正整数和加减乘除四个运算符(+ - * /)组成。

例如存在字符串 const str = '11+2-3*4+5/2*4+10/5',现在需要将高优先级运算,用小括号包裹起来,例如结果为 '11+2-(3*4)+(5/2*4)+(10/5)'。注意可能会出现连续的乘除运算,需要包裹到一起。

请用 javascript 实现这一过程


介绍一种只需遍历一次的实现方式,思路比较简单,主要用到了2个临时变量,分别用于记录当前是否在高优先级运算范围和临时值,然后根据不同优先级的运算符进行不同的处理操作。

具体的代码如下:

function addBrackets(expression) {
  const resultArr = [];

  // 定义运算符
  const symbolArr = ["+", "-", "*", "/"];

  // 定义高优先级运算符
  const highLevelSymbolArr = ["*", "/"];

  // 判断某个字符串是否是运算符
  const isSymbolFn = (str) => symbolArr.includes(str);

  // 判断某个字符串是否是高优先级运算符
  const isHighLevelSymbolFn = (str) => highLevelSymbolArr.includes(str);

  // 输入表达式的长度
  const expLen = expression.length;

  // 标记当前的遍历是否处于高优先级运算符范围
  let isInBracket = false;
  // 记录临时值
  let currentNum = "";

  for (let i = 0; i < expLen; i++) {
    const isSymbol = isSymbolFn(expression[i]);
    const isHighLevelSymbol = isSymbol && isHighLevelSymbolFn(expression[i]);

    // 处理当前字符是运算符的场景
    if (isSymbol) {
      //处理当前字符是高优先级运算符
      if (isHighLevelSymbol) {
        // 如果当前没有被标记为高优先运算符,就在前面加个括号
        if (!isInBracket) {
          currentNum = "(" + currentNum;
        }

        // 修改标记状态
        isInBracket = true;
        currentNum += expression[i];
      } else {
        // 普通运算符

        if (isInBracket) {
          // 如果之前已经在高优先级运算符范围,就需要标记结束
          resultArr.push(currentNum + ")");
          isInBracket = false;
        } else {
          resultArr.push(currentNum);
        }
        resultArr.push(expression[i]);
        currentNum = "";
      }
    } else {
      // 如果是数字,就直接进行记录
      currentNum = currentNum + expression[i];
    }
  }

  if (currentNum) {
    resultArr.push(currentNum + (isInBracket ? ")" : ""));
  }

  return resultArr.join("");
}

另外还可以使用滑动窗口的思路来实现:

滑动窗口实现

使用正则实现(2022/10/30更新)

有小伙伴提供了一种正则表达式的实现方式,供大家参考:

let text = "11+2-34+5/24+10/5+10/512";
text.match(/([0-9]{1,}[*|/]){1,}[0-9]{1,}/g).forEach((item) => {
  text = text.replace(item, `(${item})`);
});
console.log(text); // '11+2-34+(5/24)+(10/5)+(10/512)'

以上答案由“前端面试题宝典”收集、整理,PC端访问地址: https://fe.ecool.fun/

原文转自:https://fe.ecool.fun/topic/a0e34df4-b603-4b18-bcd6-ebf8c94b3325