Parsing 将括号与kotlin方式匹配

Parsing 将括号与kotlin方式匹配,parsing,kotlin,Parsing,Kotlin,我让科特林试一试;通过内容编码,我有一个字符的ArrayList,我想根据括号的匹配方式对其进行分类: (abcde) // ok characters other than brackets can go anywhere )abcde( // ok matching the brackets 'invertedly' are ok (({()})) // ok )()()([] // ok ([)] // bad can't have different overlappin

我让科特林试一试;通过内容编码,我有一个字符的ArrayList,我想根据括号的匹配方式对其进行分类:

(abcde)  // ok characters other than brackets can go anywhere
)abcde(  // ok matching the brackets 'invertedly' are ok
(({()})) // ok 
)()()([] // ok 
([)]     // bad can't have different overlapping bracket pairs
(((((    // bad all brackets need to have a match
我的解决方案出来了(递归):

//charList是一个属性
//递归启动程序的上层
private fun classifyListOfCharacters():布尔值{
var j=0
而(j
这是可行的,但你在科特林就是这样做的吗?感觉上我已经用Kotlin语法编写了java

找到了这个,我试着从操作函数的角度来思考,并将它们发送到递归中,但没有用。我很高兴能为可能的重构指明正确的方向、代码或一些伪代码


(省略了一些关于方括号的扩展方法,我认为它们的作用很清楚)

另一种可能更简单的解决方法是在迭代字符时维护方括号堆栈

当您遇到另一个括号时:

  • 如果它与堆栈顶部匹配,则弹出堆栈顶部

  • 如果它与堆栈顶部不匹配(或堆栈为空),则将其推送到堆栈上

如果堆栈末尾仍有任何括号,则表示它们不匹配,答案为
false
。如果堆栈最终为空,则答案为
true

这是正确的,因为序列中位于
i
位置的括号可以与位于
j
位置的另一个括号匹配,前提是它们之间没有不同类型的不匹配括号(位于
k
i
)。堆栈算法正好模拟了这种匹配逻辑

基本上,该算法可以在单个
for
循环中实现:

val stack = Stack<Char>()

for (c in charList) {
    if (!c.isBracket())
        continue

    if (stack.isNotEmpty() && c.matchesBracket(stack.peek())) {
        stack.pop()
    } else {
        stack.push(c)
    }
}

return stack.isEmpty()
val stack=stack()
for(字符表中的c){
如果(!c.isBracket())
持续
if(stack.isNotEmpty()&&c.matchesBracket(stack.peek())){
stack.pop()
}否则{
堆栈推送(c)
}
}
返回stack.isEmpty()
我已经重用了您的扩展名
c.isBracket(…)
c.matchesBracket(…)
。这是一个JDK类

该算法将递归和括号嵌套隐藏在括号堆栈的抽象中。比较:您当前的方法隐式使用函数调用堆栈而不是方括号堆栈,但目的是相同的:它要么查找最上面字符的匹配项,要么使用另一个字符进行更深层次的递归调用。

热键的答案(使用for循环)非常好。但是,您要求一个优化的递归解决方案。这是一个优化的函数(注意函数前面的
tailrec
修饰符):


如果您的代码能够正常工作,那么在我实现这一点时,它可能更适合,IDE建议用stdlib操作替换循环。它在'isBracket()'上过滤{}(这一个简化了imo,去掉了continue)。它还使用ForEach{}函数,这是否有优势?在这种情况下,meNote似乎不太清楚:此递归解决方案的计算复杂性因
输入而增加。drop(1)
操作:它实际上每次复制输入字符串,但只复制一个字符(并且agorithm的复杂性变为
O(n^2)
)。我建议先将字符串转换为
列表
,然后使用它的
.subList(…)
视图,该视图不会复制项目。如果我错了,请纠正我
input.drop()
委托给
String#subString
,它确实为每个
subString
调用创建新字符串。但是我没有看到任何显式迭代会增加时间复杂度。还没有确定
String#subString
是否复制底层数组的部分,这是实现定义的。事实上,自从JDK 7之后,它就已经开始使用了,尽管在JDK 6和更早的版本中没有。没有显式的迭代,但是,由于复制了字符,每次使用子字符串删除一个字符需要
O(n+(n-1)+(n-2)+…+1)=O(n^2)
time.OK。知道了。非常感谢。
val stack = Stack<Char>()

for (c in charList) {
    if (!c.isBracket())
        continue

    if (stack.isNotEmpty() && c.matchesBracket(stack.peek())) {
        stack.pop()
    } else {
        stack.push(c)
    }
}

return stack.isEmpty()
tailrec fun isBalanced(input: List<Char>, stack: Stack<Char>): Boolean = when {

    input.isEmpty() -> stack.isEmpty()

    else -> {

        val c = input.first()

        if (c.isBracket()) {
            if (stack.isNotEmpty() && c.matchesBracket(stack.peek())) {
                stack.pop()
            } else {
                stack.push(c)
            }
        }

        isBalanced(input.subList(1, input.size), stack)

    }
}

fun main(args: Array<String>) {
    println("check: ${isBalanced("(abcde)".toList(), Stack())}")
}
public static final boolean isBalanced(@NotNull String input, @NotNull Stack stack) {
      while(true) {
         CharSequence c = (CharSequence)input;
         if(c.length() == 0) {
            return stack.isEmpty();
         }

         char c1 = StringsKt.first((CharSequence)input);
         if(isBracket(c1)) {
            Collection var3 = (Collection)stack;
            if(!var3.isEmpty() && matchesBracket(c1, ((Character)stack.peek()).charValue())) {
               stack.pop();
            } else {
               stack.push(Character.valueOf(c1));
            }
         }

         input = StringsKt.drop(input, 1);
      }
   }