1. 程式人生 > >京東筆試題2:求括號匹配數目

京東筆試題2:求括號匹配數目

題目描述:

這裡寫圖片描述

描述

有一個合法的字串,合法是指左括號與右括號全部能配對,現在每次將這個序列第一個左括號刪去,在將任意一個右括號刪去,每次刪去後的序列必須合法,求有多少種方法

輸入

一個合法括號序列。

輸出

方案數。

樣例輸入

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

樣例輸出

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)。