Skip to content

根据运算优先级添加括号

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

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

请用 javascript 实现这一过程

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

具体的代码如下:

js
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更新)

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

js
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/