LeetCode第32題: 最長有效括號 longestValidParentheses(C語言)

思路1:這個序列問題,很容易聯(lián)想到用動態(tài)規(guī)劃的思路來解最長公共字符串的問題庶近,區(qū)別在于枢纠,在求最長公共字符串的時候,子狀態(tài)從兩個相鄰字符開始判斷筹裕,如果這兩個字符不相等,則包含這兩個相鄰字符的一定不是公共字符串窄驹。而對于本題朝卒,如果兩個相鄰的括號不匹配,比如兩個都是'('乐埠、'('抗斤,這兩個不匹配,但以這兩個子串為基礎(chǔ)的其他子串不一定無法組成有效的括號丈咐,比如連續(xù)四個括號分別為'( ( ) )'這樣的形式瑞眼,無法從之前計算的兩個右括號不匹配的情況推出現(xiàn)在四個括號的匹配情況。那么問題來了棵逊,針對本題的最優(yōu)子狀態(tài)應(yīng)該怎么去找呢伤疙?
通過分析:兩個匹配的左右括號,一定是相鄰最近的匹配對辆影,也就是最里層的括號一定是優(yōu)先匹配徒像,然后在逐層向外匹配,比如上述的四個連續(xù)括號'( ( ) )'的情況蛙讥,一定是中間兩個先匹配锯蛀,然后再匹配外層的兩個。如果我們在匹配第一個'('的時候键菱,已經(jīng)提前知道第二個和第三個已經(jīng)組合為一個有效括號的話谬墙,那第一個就可以直接去匹配第四個左括號了,這樣的話经备,對于第一個右括號拭抬,最長匹配有效括號長度就是4。
也就是說侵蒙,如果從左邊第一個匹配的時候造虎,提前知道他右側(cè)的已經(jīng)匹配匹配好的最大長度了,那么就可以跳過已經(jīng)匹配完成的情況了纷闺,比如'( ( ( ) ) )'這個情況算凿,在匹配第一個右括號的時候份蝴,已經(jīng)知道中間的兩個括號對的話,則直接跳過氓轰,去匹配第六個做括號婚夫,即可得出最長匹配有效括號長度是6。
我們可以嘗試從字符串的末端先提前生成上述兩個情況的字符串匹配的結(jié)果署鸡,首先建立一個與輸入字符串等長的數(shù)組a案糙,用于保存每個字符串位置能匹配到的最長的長度,比如對于'( ( ( ) ) )'當(dāng)計算第一個右括號的時候靴庆,已經(jīng)知道a[1]的值是4时捌,也就是從這個位置向右移動四個位置,可以算作第二個字符的匹配炉抒,所以計算第一個右括號的話奢讨,直接去匹配第五個。這就是我們要設(shè)計的動態(tài)規(guī)劃的子狀態(tài)了焰薄。
這里還有一個問題拿诸,對于'( ( ( ) ) ) ( )',當(dāng)計算第一個的值時蛤奥,如果跳過這個a[1]的值4的長度之后佳镜,順利匹配到第五個字符僚稿,而且匹配成功了凡桥,但是第五個字符的后面的字符串依然是一個匹配完成的字符串,則還要加上這段長度蚀同,然后再算作第一個字符的整體長度
這就是完整的思路了缅刽。具體代碼如下:

int longestValidParentheses(const char *s)
{
    int n=strlen(s);
    if(n == 0)
        return 0;
    int i,j;
    int dp[n];
    int max=0;
    
    for(i=0;i<n;i++)
        dp[i]=0;
    for(i=n-2;i>=0;i--)
    {
        if(s[i]=='(')
        {
            j=i+1+dp[i+1];
            if(j<n && s[j]==')')
            {
                dp[i]=dp[i+1]+2;
                if(j+1<n)
                    dp[i]+=dp[j+1];
            }
        }
        if(max<=dp[i])
            max=dp[i];
    }
    return max;
}

思路2:在思路1中我們知道,在一個括號序列里蠢络,當(dāng)遇到一個左括號')'時衰猛,需要找到其左側(cè)與其最近的右括號'(',而不是最靠前的右括號'('刹孔,比如輸入序列'( ( ) )'啡省,很明顯第一個')'找到的時候內(nèi)部的右括號'('也就是第二個右括號'(',而第一個右括號'('髓霞,需要等待其右邊沒有待匹配的右括號'('時候才開始匹配卦睹,針對本例,也就是匹配完內(nèi)部的括號對再匹配外側(cè)的括號對方库。
那么结序,當(dāng)我們遇到輸入序列的時候,如果首先遇到一個右括號'('纵潦,
1徐鹤、如果其第二個輸入的是左括號')'垃环,則直接完成匹配;
2返敬、如果其第二個輸入的依然是右括號'('時候呢遂庄?我們是不是就要把第一個輸入的右括號'('掛起,等第二個輸入的右括號'('匹配到后邊的左括號了劲赠,再來匹配被掛起的第一個右括號'('涧团。
遇到這樣的情形,可以將遇到的右括號'('推入棧stack[]數(shù)組中经磅,并記錄stack[top]為輸入序列的索引位置泌绣,每遇到一個左括號')',則從棧中推出一個右括號'('预厌。

現(xiàn)在問題來了阿迈,我們現(xiàn)在知道如何去找到兩個匹配的括號了,那么轧叽,怎么來計算最長的有效括號呢苗沧,上一步,每一次匹配成功炭晒,我們可以獲取到兩個有效括號對的索引待逞,我們可以新建一個與輸入字符串等長的mark數(shù)組,每遇到一個匹配成功的括號對网严,就將兩個索引標(biāo)記下來识樱。等循環(huán)遍歷完成,統(tǒng)計mark數(shù)組的最長連續(xù)標(biāo)記的長度即可震束。廢話不說了怜庸,上代碼。

int longestValidParentheses(char* s) {
    int len=strlen(s);
    if(len <= 1)
        return 0;
    int* mark=(int*)malloc(sizeof(int)*len);
    for(int i=0;i < len;i++)
        mark[i] = -1;
    int* stack=(int*)malloc(sizeof(int)*len);
    int top=0;
    for(int i = 0; i < len; i++){
        if(s[i]=='(')
            stack[top++]=i;
        else{
            if(top!=0){
                mark[stack[top-1]]=0;
                mark[i]=0;
                top--;
              }
          }
    }
          
    int count=0;
    int newCount=0;
    for(int i = 0; i < len;i++){
        if(mark[i]!= -1)
            newCount++;
        else{
            if(newCount>count){
                count=newCount;
            }
            newCount=0;
        }
    }
    if(newCount>count)count=newCount;
    return count;
}

本系列文章垢村,旨在打造LeetCode題目解題方法割疾,幫助和引導(dǎo)同學(xué)們開闊學(xué)習(xí)算法思路,由于個人能力和精力的局限性嘉栓,也會參考其他網(wǎng)站的代碼和思路宏榕,如有侵權(quán),請聯(lián)系本人刪除侵佃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末麻昼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子趣钱,更是在濱河造成了極大的恐慌涌献,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件首有,死亡現(xiàn)場離奇詭異燕垃,居然都是意外死亡枢劝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門卜壕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來您旁,“玉大人,你說我怎么就攤上這事轴捎『缀校” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵侦副,是天一觀的道長侦锯。 經(jīng)常有香客問我,道長秦驯,這世上最難降的妖魔是什么尺碰? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮译隘,結(jié)果婚禮上亲桥,老公的妹妹穿的比我還像新娘。我一直安慰自己固耘,他們只是感情好题篷,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厅目,像睡著了一般番枚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上璧瞬,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天户辫,我揣著相機與錄音,去河邊找鬼嗤锉。 笑死,一個胖子當(dāng)著我的面吹牛墓塌,可吹牛的內(nèi)容都是我干的瘟忱。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼苫幢,長吁一口氣:“原來是場噩夢啊……” “哼访诱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起韩肝,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤触菜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哀峻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涡相,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡哲泊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了催蝗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片切威。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖丙号,靈堂內(nèi)的尸體忽然破棺而出先朦,到底是詐尸還是另有隱情,我是刑警寧澤犬缨,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布喳魏,位于F島的核電站,受9級特大地震影響怀薛,放射性物質(zhì)發(fā)生泄漏截酷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一乾戏、第九天 我趴在偏房一處隱蔽的房頂上張望迂苛。 院中可真熱鬧,春花似錦鼓择、人聲如沸三幻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至摆出,卻和暖如春朗徊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偎漫。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留象踊,地道東北人温亲。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像杯矩,于是被迫代替她去往敵國和親栈虚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361