京東筆試題2:求括號匹配數目
阿新 • • 發佈:2018-12-31
題目描述:
描述
有一個合法的字串,合法是指左括號與右括號全部能配對,現在每次將這個序列第一個左括號刪去,在將任意一個右括號刪去,每次刪去後的序列必須合法,求有多少種方法
輸入
一個合法括號序列。
輸出
方案數。
樣例輸入
()()()() (((())))()() |
樣例輸出
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)。