京东笔试题2:求括号匹配数目

来源:互联网 发布:xp中windows设置在哪 编辑:程序博客网 时间:2024/06/05 02:58

题目描述:

这里写图片描述

描述

有一个合法的字符串,合法是指左括号与右括号全部能配对,现在每次将这个序列第一个左括号删去,在将任意一个右括号删去,每次删去后的序列必须合法,求有多少种方法

输入

一个合法括号序列。

输出

方案数。

样例输入

()()()()
(((())))()()

样例输出

1
24

算法思想:

这道题惯性思维是使用深度搜索,深度搜索函数有两个参数,输入字符串与标志位,其中标志位用于标志查询的是左括号还是右括号,如果是左括号,则将去掉该左括号的字符串传入函数,并将标志设置为1,搜索右括号,如果匹配,则结果数加1,然后去掉该右括号,据需递归。
当然这道题目还可以使用逆向思维,因为从左往右扫描,每次选取的右括号会影响下次计算的结果值。所以可以考虑从右往左进行扫描,这样选取左括号就不会影响下次的扫描结果。从右往左扫描,如果是右括号则计数count + 1,如果遇到左括号,则表明该左括号可以有n中选择,且n–,继续扫描。

深度扫描源代码

#include<iostream>#include<vector>#include <string>using namespace std;int ans;/*判断是否匹配合法函数*/bool isr(string s){    int t = 0;    for (int i = 0; i<s.size(); i++)    {        if (s[i] == '(')        {            t++;        }        else        {            if (t<1)            {                return false;            }            else            {                t--;            }        }    }    return true;}/*深度搜索函数*/int fun(string s, int k){    //当k = 0时,扫描查找左括号    if (k == 0)    {        if (s.size() == 0)        {            ans++;            return 0;        }        for (int i = 0; i<s.size(); i++)        {            //去除该左括号,扫描右括号            if (s[i] == '(')            {                string ss = s.substr(0, i);                cout << "ss = " << ss << endl;                string sb = s.substr(i + 1);                ss += sb;                cout << ss << " " << sb << endl;                fun(ss, 1);                break;            }        }    }    //扫描右括号    else    {        for (int i = 0; i<s.size(); i++)        {            if (s[i] == ')')            {                string ss = s.substr(0, i);                string sb = s.substr(i + 1);                ss += sb;                if (isr(ss))                {                    fun(ss, 0);                }            }        }    }    return 0;}int main(){    string s;    cin >> s;    ans = 0;    fun(s, 0);    cout << ans << endl;    return 0;}

逆向扫描源代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include <string>using namespace std;const long long mod = 10000000007ll;char ch[20000005];long long ans = 1;int tot;int main(){    string str;    cin >> str;    int len = str.size();    for (int i = len - 1; i >= 0; i--)    {        if (str[i] == ')')tot++;        else if (str[i] == '('){            ans = (ans*tot) % mod;            tot--;        }    }    printf("%I64d", ans);    return 0;}

算法时间复杂度:

第一种深度递归方法时间复杂度是O(2^n),第二种逆向思维扫描的时间复杂度为O(n)。