检查字符串是否平衡

时间:2013-02-19 03:32:19

标签: java string algorithm recursion balance

我想检查字符串是否与递归平衡。我在论坛上发现了与此问题相关的一些其他帖子,一些答案是我不懂的编程语言。在Stack Overflow上阅读类似的问题之后,我可以用堆栈来完成它,我该怎么递归呢?

private static boolean isBalanced(String s, char match)
{
    char c;

    if(s.isEmpty())
        return true;

    for(int i = 0; i < s.length(); i++)
    {
        c = s.charAt(i); 

        if(c == '{') 
            return isBalanced(s.substring(i+1), '}');

        else if(c == '[')
            return isBalanced(s.substring(i+1), ']');

        else if(c == '(')
            return isBalanced(s.substring(i+1), ')');

        // Closing matches.
        else if(c == match)
            return true;

    }

    return 
}

请帮忙。

编辑:不,我不希望任何人为我编码,事实上,我会知道如何做到这一点。这就是为什么我不理解其他语言的答案,因为它们太过于特定于语言而不是算法。

EDIT2:是平衡的是{}()[]及其任何组合,例如[()]

5 个答案:

答案 0 :(得分:3)

使用递归执行此操作的想法与使用堆栈的原理相同。 调用堆栈是你的LIFO结构,你可以按照它进行调用。

采用简单的平衡字符串:

String bal = "(This is (perfectly) balanced.)";

首先要做的是 - 让我们建立条件。

  • 我们不关心任何不是paren,支撑或支架的东西。我们可以忽视任何不属于这三个角色的角色。
  • 如果我们遇到一个paren,大括号或括号,我们会立即递归并搜索其余字符串上的匹配项。也就是说,如果我从bal开始,我就会在bal.substring(1)进行推算。

我不会使用循环,因为你仍然遍历整个String。我宁愿消耗它,以减少我必须回溯的字符数量。

答案 1 :(得分:3)

这是算法,我刚刚尝试过并且有效。想法是,在每个开口支架上,您期望关闭同一类型的支架。上面的函数需要像isBalanced("([2+3])", 0, new Stack<Character>())一样调用。使用stack维护期望的字符。

public static boolean isBalanced(String s, int i, Stack<Character> expected) {
    /* end has reached and not expecting anything then break */
    if (i == s.length())
        return expected.isEmpty();

    char c = s.charAt(i);
    /* expecting something and it is a closing type */
    /* then it should match expecting type */
    if (c == '}' || c == ')' || c == ']') {
        char e = expected.isEmpty() ? '\0' : expected.pop();
        if(e != c)
            return false;
    }

    if(c == '{') 
        expected.push('}');
    else if(c == '[')
        expected.push(']');
    else if(c == '(')
        expected.push(')');

    /* call recursively with i + 1 */ 
    return isBalanced(s, i + 1, expected);

}

这是非堆栈版本的代码: 通话就像这样isBalanced2("{[]}[()]", 0, '\0') < 0 ? false : true

public static int isBalanced2(String s, int i, char match)
{
    if(i >= s.length())
        return match == '\0' ? 0 : -1;

    char c;
    int j;
    for(j = i; j < s.length(); j++)
    {
        c = s.charAt(j); 
        /* any of the closing type */
        if(c == ']' || c == '}' || c == ')') {
            return c == match ? j : -1;
        }

        if(c == '{') 
            j = isBalanced2(s, j + 1, '}');

        else if(c == '[')
            j = isBalanced2(s, j + 1, ']');

        else if(c == '(')
            j = isBalanced2(s, j + 1, ')');

        if(j == -1)
            break;
    }

    return match != '\0' ? -1 : j;
}

答案 2 :(得分:1)

直接循环是这里最快的解决方案:

private static boolean isBalanced(String s)
{
    char[] chars = new char[s.length()];
    int size = 0;
    for (int i = 0; i < s.length(); i++)
    {
        char c = s.charAt(i);
        if (c == '{' || c == '(' || c == '[') chars[size++] = c;
        if (c == '}' && (size == 0 || chars[--size] != '{')) return false;
        if (c == ')' && (size == 0 || chars[--size] != '(')) return false;
        if (c == ']' && (size == 0 || chars[--size] != '[')) return false;
    }

    return true;
}

算法的复杂性 O(N)没有子串等。

答案 3 :(得分:0)

让我们正式接近这一点,以增加我们在没有大量调试的情况下提出可行解决方案的可能性。

什么是平衡字符串?这是一个简单的语法:

BalancedString: Sequence end-of-string;

Sequence:
    Fragment Sequence |
    (* empty *);

Fragment:
    '(' Sequence ')' |
    '[' Sequence ']' |
    '{' Sequence '}' |
    any-character-not-in-'()[]{}';

请注意,此语法会生成(hello)[[good]{bye}]之类的字符串,其中包含多个&#34;顶级&#34;基。

现在让我们把它变成一个递归下降的解析器。每个非终结符(BalancedStringSequenceFragment)都会成为一个函数。我们将从解析&#39; BalancedString&#39;的函数开始。非末端:

private static bool parseBalancedString(String input, int offset) {
    offset = parseSequence(input, offset);
    return offset == input.length();
}

请注意,此函数希望parseSequence返回停止解析的偏移量。我们接下来写parseSequence。我们将使用循环而不是直接递归。

private static int parseSequence(String input, int offset) {
    bool parseSucceeded = true;
    while (parseSucceeded) {
        int newOffset = parseFragment(input, offset);
        parseSucceeded = newOffset > offset;
        newOffset = offset;
    }
    return offset;
}

请注意parseSequence期望parseFragment返回它停止解析的偏移量,并且它应该返回它失败时传递的偏移量。现在我们写parseFragment。我们将其三个相似产品中的公共代码提取到辅助函数中。

private static int parseFragment(String input, int offset) {
    if (offset >= input.length()) {
        return offset;
    }

    switch (input.charAt(offset)) {
        case '(': return helpParseFragment(input, offset, ')');
        case '[': return helpParseFragment(input, offset, ']');
        case '{': return helpParseFragment(input, offset, '}');
        default: return offset + 1;
    }
}

辅助函数期望接收开启器的偏移量,以便在失败时返回该偏移量。如果成功,则返回刚刚越过闭合器的偏移量。

private static int helpParseFragment(String input, int offset, char closer) {
    int newOffset = parseSequence(input, offset + 1);
    if (newOffset > offset && newOffset < input.length() && input.charAt(newOffset) == closer) {
        return newOffset + 1;
    } else {
        return offset;
    }
}

答案 4 :(得分:0)

import java.util.*;
class Solution{

   public static void main(String []argh)
   {
      Scanner sc = new Scanner(System.in);


      while (sc.hasNext()) 
      {
         String input=sc.next();
         Stack<Character> stacky = new Stack<>();
          int x=0,y=0,z=0,a=0,b=0,c=0;
         for (int i = 0; i < input.length(); i++) 
         {

                switch(input.charAt(i)) 
                {
                    case '[' : a++; break;
                    case '{' : b++;break;

                     case '(' : c++;
                    break;

                    case ']' :x++; break;
                    case '}' : y++; break;

                     case ')' :
                            z++;
                    break;



                default: stacky.push(input.charAt(i));
          }


            //Complete the code

            if(x==a && y==b && z==c)
                {

                System.out.println("true");

                 }
             else
                 {
                 System.out.println("false");
             }




      }

   }
   }}

the documentation