算法練習(xí):回文子字符串的個(gè)數(shù)(多種方法)

一.前言

今天介紹一道相對(duì)簡(jiǎn)單的練習(xí)題叉橱,同樣是來(lái)自LeetCode儒飒。

回文子字符串的個(gè)數(shù),給定一個(gè)字符串 s 诫惭,請(qǐng)計(jì)算這個(gè)字符串中有多少個(gè)回文子字符串惜傲。具有不同開(kāi)始位置或結(jié)束位置的子串,即使是由相同的字符組成贝攒,也會(huì)被視作不同的子串盗誊。

示例1:

輸入:s = "abc"
輸出:3
解釋:三個(gè)回文子串: "a", "b", "c"

示例2:

輸入:s = "aaa"
輸出:6
解釋:6個(gè)回文子串: "a", "a", "a", "aa", "aa", "aaa"

題目來(lái)源:LeetCode

二.題解

其實(shí)關(guān)于回文的題有很多種,而解法更是多種多樣隘弊,今天介紹兩種方法哈踱,遞歸中心拓展

1.遞歸

簡(jiǎn)單來(lái)說(shuō)遞歸就是一個(gè)函數(shù)調(diào)用自己本身的行為就叫遞歸梨熙。遞歸具有代碼簡(jiǎn)潔开镣,易讀的特點(diǎn),但是缺點(diǎn)也不容忽視:

a).運(yùn)行效率較低咽扇。
b).可能會(huì)導(dǎo)致棧溢出邪财,如果遞歸次數(shù)太多陕壹,需要在內(nèi)存棧中分配空間以保存參數(shù)以及臨時(shí)變量就會(huì)過(guò)多,當(dāng)超出棧的容量树埠,就會(huì)導(dǎo)致棧溢出糠馆。

我們思路是這樣的:首先通過(guò)遍歷找到所有的子串,然后再判斷子串是否是回文怎憋。那么怎么判斷是否是回文呢又碌?比如這樣的一個(gè)字符串abcba,我們判斷其是否為回文,可以先判斷第一個(gè)和最后一個(gè)字符是否相同绊袋,再判斷第二個(gè)字符和倒數(shù)第二個(gè)字符是否相同...直到全部判斷完畢毕匀,這個(gè)過(guò)程中,我們反復(fù)做著相同的工作癌别,因此可以使用遞歸皂岔,來(lái)看看代碼吧:

class Solution {
    public int countSubstrings(String s) {
        int result = 0;//最終結(jié)果
        //兩層循環(huán)展姐,從字符串首部開(kāi)始遍歷處所有子字符串
        for (int i = 0; i < s.length(); i++) {
            for (int j = i; j < s.length(); j++) {
                //每個(gè)子字符串調(diào)用isHuiwen凤薛,若返回 true 則 result + 1
                if (isHuiwen(s, i, j)) {
                    result++;
                }
            }
        }
        return result;
    }
    //isHuiwen需要三個(gè)參數(shù),s 是字符串诞仓,i 是子字符串第一個(gè)字符缤苫,j 是子字符串的最后一個(gè)字符
    public static boolean isHuiwen(String s, int i, int j) {
        //兩種情況返回true(1,2)
        //1.當(dāng)子字符串的長(zhǎng)度是奇數(shù)時(shí),此時(shí)回文中心只有一個(gè)墅拭,當(dāng)遞歸到 i == j時(shí)活玲,說(shuō)明全部首尾字符判斷完畢,全部相等谍婉,返回true
        if (i == j) return true;
        else {
            if (s.charAt(i) != s.charAt(j)) {
                //如果二者不相等舒憾,直接返回false,退出遞歸
                return false;
            } else {
                //2.當(dāng)子字符串的長(zhǎng)度為偶數(shù)穗熬,此時(shí)回文中心是兩個(gè)字符镀迂,由于上面的if中已經(jīng)判斷 i 和 j是相同的
                //因此到這里也將首尾字符全部判斷完畢,全部相等唤蔗,返回true
                if (i + 1 == j) {
                    return true;
                } else return isHuiwen(s, ++i, --j);
                //如果程序走到這兒探遵,說(shuō)明不滿足上面任意一種情況,因此在調(diào)用函數(shù)進(jìn)一步判斷 ++i 和 --j 是否相等
            }
        }
    }
}

我們上面這種方法找出子字符串需要兩層循環(huán)妓柜,時(shí)間復(fù)雜度為O(n^2) 而判斷它是否為回文又是O(n)箱季,因此總的復(fù)雜度為O(n^3)。顯然效率不高棍掐,那我們?cè)賮?lái)看看LeetCode官方題解吧藏雏!——中心拓展

2.中心拓展

大致思路:我們從每一個(gè)可能成為回文中心的點(diǎn)開(kāi)始,若前后字符相等就拓展作煌,反之掘殴,則停止拓展赚瘦。

當(dāng)子字符串是奇數(shù)時(shí),回文中心是一個(gè)奏寨;當(dāng)子字符串是偶數(shù)個(gè)時(shí)起意,回文中心是兩個(gè)。有沒(méi)有一種方法可以統(tǒng)一二者呢服爷?答案是有的杜恰。通過(guò)規(guī)律我們可以發(fā)現(xiàn):無(wú)論子字符串長(zhǎng)度是偶數(shù)還是奇數(shù)获诈,我們都需要遍歷 2n - 1 次字符串仍源,換句話說(shuō)就是有 2n - 1 個(gè)回文中心,

class Solution {
    public int countSubstrings(String s) {
        int n = s.length(), ans = 0;
        for (int i = 0; i < 2 * n - 1; ++i) {
            //向前拓展從i開(kāi)始舔涎,向后拓展從r開(kāi)始
            int l = i / 2, r = i / 2 + i % 2;
            //當(dāng)子字符串個(gè)數(shù)為偶數(shù)時(shí)笼踩,i 和 r 相等 
            while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
                //當(dāng)前后字符相等且 i 和 r 未越界時(shí)
                //開(kāi)始向兩邊拓展
                --l;
                ++r;
                ++ans;
            }
        }
        return ans;
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市亡嫌,隨后出現(xiàn)的幾起案子嚎于,更是在濱河造成了極大的恐慌,老刑警劉巖挟冠,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件于购,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡知染,警方通過(guò)查閱死者的電腦和手機(jī)肋僧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)控淡,“玉大人嫌吠,你說(shuō)我怎么就攤上這事〔籼浚” “怎么了辫诅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)涧狮。 經(jīng)常有香客問(wèn)我炕矮,道長(zhǎng),這世上最難降的妖魔是什么者冤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任吧享,我火速辦了婚禮,結(jié)果婚禮上譬嚣,老公的妹妹穿的比我還像新娘钢颂。我一直安慰自己,他們只是感情好拜银,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布殊鞭。 她就那樣靜靜地躺著遭垛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪操灿。 梳的紋絲不亂的頭發(fā)上锯仪,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音趾盐,去河邊找鬼庶喜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛救鲤,可吹牛的內(nèi)容都是我干的久窟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼本缠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斥扛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起丹锹,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤稀颁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后楣黍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體匾灶,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年租漂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了阶女。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窜锯,死狀恐怖张肾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锚扎,我是刑警寧澤吞瞪,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站驾孔,受9級(jí)特大地震影響芍秆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翠勉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一妖啥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧对碌,春花似錦荆虱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诉位。三九已至,卻和暖如春菜枷,著一層夾襖步出監(jiān)牢的瞬間苍糠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工啤誊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岳瞭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓蚊锹,卻偏偏與公主長(zhǎng)得像瞳筏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子枫耳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容