在输入文本中匹配平衡和嵌套大括号

时间:2013-09-15 17:41:53

标签: c++ algorithm

我参加了一个测验,我给出了代码但是自动测试显示八个测试用例中的一个失败了。 我自己多次测试我的代码,但都通过了。我找不到问题所在。

问题是设计一种算法来检查字符串中的括号是否匹配。

1)只需考虑圆括号()和方括号[],省略哦字符。
2)每对括号应相互匹配。这意味着匹配)[匹配] 3)不允许交叉,例如:([)]。有两对括号,但它们相互交叉。

为了解决这个问题,我的方法描述如下:

  1. 搜索整个输入字符串中的每个字符,索引从0到str.size() - 1.
  2. 使用两个堆栈记录开始标记([,每个类型都在一个堆栈中。遇到其中一个时,将其索引推送到相应的堆栈中。
  3. 当鼓励结束标记)]时,我们会弹出相应的堆栈。
  4. 在弹出之前,检查两个堆栈的顶部,当前堆栈应该具有​​最大索引,否则这意味着与另一个类型有不匹配的开始标记,因此可以通过这种方式检查交叉。
  5. 我的代码就在这里:

    #include <iostream>
    #include <stack>
    using namespace std;
    
    int main()
    {
        string str;
        cin >> str;
    
        stack<int> s1, s2;
        int result = 0;
        for (int ix = 0, len = str.size(); ix < len; ix++)
        {
            if (str[ix] == '(')
            {
                s1.push(ix);
            }
            else if (str[ix] == '[')
            {
                s2.push(ix);
            }
            else if (str[ix] == ')')
            {
                if (s1.empty() || (!s2.empty() && s1.top() < s2.top()))
                {
                    result = 1;
                    break;
                }
                s1.pop();
            }
            else if (str[ix] == ']')
            {
                if (s2.empty() || (!s1.empty() && s2.top() < s1.top()))
                {
                    result = 1;
                    break;
                }
                s2.pop();
            }
            else
            {
                // do nothing
            }
        }
        if (!s1.empty() || !s2.empty())
        {
            result = 1;
        }
        cout << result << endl;
    }
    

    如前所述,这个问题可以通过堆栈来解决,所以我修改了我的代码,这里是单栈版本。 [关键点不是要认为白色更好,但是我的代码有什么错误。]

    #include <iostream>
    #include <stack>
    using namespace std;
    
    int main()
    {
        string str;
        cin >> str;
    
        stack<char> s;
        const char *p = str.c_str();
        int result = 0;
        while (*p != '\0')
        {
            if (*p == '(' || *p == '[')
            {
                s.push(*p);
            }
            else if (*p == ')')
            {
                if (s.empty() || s.top() != '(')
                {
                    result = 1;
                    break;
                }
                s.pop();
            }
            else if (*p == ']')
            {
                if (s.empty() || s.top() != '[')
                {
                    result = 1;
                    break;
                }
                s.pop();
            }
            else
            {
                // do nothing
            }
            p++;
        }
        if (!s.empty())
        {
            result = 1;
        }
        cout << result << endl;
    }
    

1 个答案:

答案 0 :(得分:1)

当使用格式化输入来读取std::string时,只读取第一个单词:跳过前导whitespate后,将读取一个字符串,直到遇到第一个空格。因此,输入( )应该匹配,但std::cin >> str只能读取(。因此,输入应该如下所示:

if (std::getline(std::cin, str)) {
    // algorithm for matching parenthesis and brackets goes here
}

使用std::getline()仍假设输入如何呈现,即它在一行上。如果算法应该处理来自std::cin的整个输入,我会使用

str.assign(std::istreambuf_iterator<char>(std::cin),
           std::istreambuf_iterator<char>());

虽然我认为算法是不必要的复杂(在堆栈存储括号的类型就足够了),我也认为它应该工作,即我发现的唯一问题是输入的方式得到了。