如何递归平衡括号



我正在研究一些代码来平衡括号,这个问题被证明对算法最有用。

用我的第一语言(PHP)实现了它,但我正在学习Scala并尝试转换代码。

这是我的PHP代码:

function balanced($string) {
  return isBalanced($string, "");
}
function isBalanced($chars, $stack) {
  if (!strlen($chars))
    return empty($stack);
  switch ($chars[0]) {
    case '(':
      // prepend stack with '(', move to next character
      return isBalanced(substr($chars, 1), $chars[0] . $stack);
    case ')':
      // if '(' seen previously, shift stack, move to next character
      return !empty($stack) && isBalanced(substr($chars, 1), substr($stack, 1));
    default:
      // do nothing to stack, move to next character
      return isBalanced(substr($chars, 1), $stack);
  }
} 

我已经测试过了,它有效。但是,当我将其转换为 Scala 时,它在平衡字符串上失败。

我的 Scala 代码:

object Main {
  def balance(chars: List[Char]): Boolean = {
    def balanced(chars: List[Char], stack: String): Boolean = {
      if (chars.isEmpty)
        stack.isEmpty
      else if (chars.head == ')')
        balanced(chars.tail, chars.head + stack)
      else if (chars.head == '(')
        !stack.isEmpty && balanced(chars.tail, stack.tail)
      else
        balanced(chars.tail, stack)
    }
    balanced(chars, "")
  }
}

我很欣赏这不是最好的 Scala 代码,但我才刚刚开始。一些测试:

balance("(if (0) false (x))".toList) - fails
balance("profit and loss (P&L).n(cashflow)".toList) - fails
balance(":)".toList) - passes
balance(")(()".toList) - passes

PHP 等效项通过了所有这些测试。我在 Scala 实现中做错了什么?

对于它的价值,这里有一个更惯用的 Scala 实现:

def balance(chars: List[Char]): Boolean = {
  @tailrec def balanced(chars: List[Char], open: Int): Boolean = 
    chars match {
      case      Nil => open == 0
      case '(' :: t => balanced(t, open + 1)
      case ')' :: t => open > 0 && balanced(t, open - 1)
      case   _ :: t => balanced(t, open)
    }
  balanced(chars, 0)
}

为了完整起见,我从另一个 SO 问题中找到了一个更简洁的"scala 式"实现:

def balance(chars: List[Char]): Boolean = chars.foldLeft(0){
  case (0, ')') => return false
  case (x, ')') => x - 1
  case (x, '(') => x + 1
  case (x, _  ) => x
} == 0

与Aaron Novstrup的答案相同,但使用"if else"。我也在参加同一门课程,但我们只被教导到如果/否则到目前为止。

def balance(chars: List[Char]): Boolean = {
    def balanced(chars: List[Char], open: Int): Boolean = 
      if (chars.isEmpty) open == 0
      else if (chars.head == '(') balanced(chars.tail, open + 1)
      else if (chars.head == ')') open > 0 && balanced(chars.tail, open - 1)
      else balanced(chars.tail, open)
    balanced(chars, 0)
}

你混淆了()的情况。

您可以使用递

归以有效的方式解决问题,而不是使用开关大小写。

以下是我的代码,可以在递归的帮助下实现相同的目标。您需要将字符串转换为我的方法的列表。

法典:

object Balance {
  def main(args: Array[String]): Unit = {
    var paranthesis = "(234(3(2)s)d)" // Use your string here
    println(bal(paranthesis.toList)) // converting the string to List 
  }
  def bal(chars: List[Char]): Boolean ={
   // var check  = 0
    def fun(chars: List[Char],numOfOpenParan: Int): Boolean = {
      if(chars.isEmpty){
        numOfOpenParan == 0
      }
      else{
        val h = chars.head
        val n = 
          if(h == '(') numOfOpenParan + 1
          else if (h == ')') numOfOpenParan - 1
          else numOfOpenParan 
       // check  = check + n
        if (n >= 0) fun(chars.tail,n)
        else false 
      }
    }
    fun(chars,0)
  }
}

我的解决方案

def balance(chars: List[Char]): Boolean = {
 var braceStack = new Stack[Char]()
def scanItems(strList:List[Char]):Boolean = {
   if(strList.isEmpty)
       braceStack.isEmpty
   else{
      var item = strList.head
      item match {
        case '(' => braceStack.push(item)
                    scanItems(strList.tail)
        case ')'=> if(braceStack.isEmpty){
                        false
                    }
                    else {
                      braceStack.pop
                      scanItems(strList.tail)
                    }
        case _ => scanItems(strList.tail)
      }
    }
 }
 scanItems(chars)

}

  val myStack = new Stack[Char]
  def balance(chars: List[Char]): Boolean = {
    def processParanthesis(x: Char, a: List[Char]): Stack[Char] = {
      if (x == '(') {
        myStack.push('(');
      } else if (x == ')') {
        if (!myStack.empty())
          myStack.pop();
        else
          myStack.push(')');
      }
      if (a.length == 0)
        return myStack;
      else
        return processParanthesis(a.head, a.tail);
    }
    return processParanthesis(chars.head, chars.tail).empty();
  }

添加到Vigneshwaran的答案中(包括注释和过滤不必要的字母以避免额外的递归调用):

def balance(chars: List[Char]): Boolean = {
  @scala.annotation.tailrec
  def recurs_balance(chars: List[Char], openings: Int): Boolean = {
    if (chars.isEmpty) openings == 0
    else if (chars.head == '(') recurs_balance(chars.tail, openings + 1)
    else openings > 0 && recurs_balance(chars.tail, openings - 1)
  }
  recurs_balance(chars.filter(x => x == '(' || x == ')'), 0)
}

看来我们正在参加同一门课程。 我的解决方案:

def balance(chars: List[Char]): Boolean = 
doBalance(chars, 0) == 0;
def doBalance(chars: List[Char], parenthesisOpenCount: Int): Int =
if(parenthesisOpenCount <0) -100;
else
if(chars.isEmpty) parenthesisOpenCount
else
  chars.head match {
  case '(' => return doBalance(chars.tail, parenthesisOpenCount+1) 
  case ')' => return doBalance(chars.tail, parenthesisOpenCount-1)
  case _ => return doBalance(chars.tail, parenthesisOpenCount)
}

最新更新