【面試現(xiàn)場(chǎng)】如何找到字符串中的最長(zhǎng)回文子串棋枕?

小史是一個(gè)應(yīng)屆生,雖然學(xué)的是電子專業(yè)妒峦,但是自己業(yè)余時(shí)間看了很多互聯(lián)網(wǎng)與編程方面的書重斑,一心想進(jìn)BAT互聯(lián)網(wǎng)公司。

今天他又去一家互聯(lián)網(wǎng)小巨頭公司面試了肯骇。

【面試現(xiàn)場(chǎng)】

小史:只要先對(duì)比第一個(gè)字符和倒數(shù)第一個(gè)字符窥浪,再對(duì)比第二個(gè)字符和倒數(shù)第二個(gè)字符,以此類推笛丙。如果都相等漾脂,那就是回文串了。

題目:給你一個(gè)字符串胚鸯,找出里面最長(zhǎng)的回文子串骨稿。

例如

輸入abcdcef,那么輸出應(yīng)該是cdc

輸入adaelele姜钳,輸出應(yīng)該是elele

半分鐘過(guò)去了。

小史:可以遍歷整個(gè)字符串哥桥,把每個(gè)字符和字符間的空隙當(dāng)作回文的中心辙浑,然后向兩邊擴(kuò)展來(lái)找到最長(zhǎng)回文串。

小史這次搶著分析時(shí)間和空間復(fù)雜度拟糕。

一分鐘過(guò)去了判呕。

【請(qǐng)教大神】

小史回到學(xué)校,把面試情況和呂老師說(shuō)了一下已卸。

呂老師:比如cabadabae用中心擴(kuò)展的算法佛玄,我已經(jīng)知道了第三位為中心的aba和第5位為中心的abadaba是回文硼一,那么在判斷第7位為中心的回文串的時(shí)候累澡,有什么已知信息嗎?

小史:已知第5位為中心的abadaba是回文般贼,由回文的特性愧哟,就能夠知道2-4位和6-8位對(duì)稱奥吩,而又知道第3位為中心的aba是回文,所以2-4位是回文蕊梧。這樣的話霞赫,6-8位肯定是回文。

小史拿著筆在紙上畫了半天肥矢,突然大叫一聲端衰。

小史:由于之前的計(jì)算已經(jīng)知道了第5位為中心的abadaba是回文,而第4位為中心的a的回文長(zhǎng)度是1甘改,所以第6位為中心的回文長(zhǎng)度只能是1旅东,不用再去擴(kuò)展判斷了。

小史:以第7位為中心的回文串的計(jì)算十艾,由之前分析已經(jīng)知道最小長(zhǎng)度是3了抵代,但是還是需要進(jìn)行擴(kuò)展,因?yàn)榈?位是什么根據(jù)之前的信息無(wú)法得知忘嫉,需要擴(kuò)展進(jìn)行探索荤牍。

小史:而以第6位為中心的回文串的計(jì)算,并不需要進(jìn)行探索了庆冕,因?yàn)楦鶕?jù)之前第5位為回文中心串的信息和第4位為回文中心串的信息已經(jīng)可以推斷第6位為回文中心串的長(zhǎng)度只能為1康吵。

小史:當(dāng)然可以。

1愧杯、首先涎才,我們要記錄下目前已知的回文串能夠覆蓋到的最右邊的地方,就像案例中的第8位

2力九、同時(shí)耍铜,覆蓋到最右邊的回文串所對(duì)應(yīng)的回文中心也要記錄,就像案例中的第5位

3跌前、以每一位為中心的回文串的長(zhǎng)度也要記錄棕兼,后面進(jìn)行推斷的時(shí)候能用到,就像案例中用到的以第3位為中心的回文和第4位為中心的回文

4抵乓、對(duì)于新的中心伴挚,我們判斷它是否在右邊界內(nèi),若在灾炭,就計(jì)算它相對(duì)右邊界回文中心的對(duì)稱位置茎芋,從而得到一些信息,同時(shí)蜈出,如果該中心需要進(jìn)行擴(kuò)展田弥,則繼續(xù)擴(kuò)展就行。

【編碼實(shí)現(xiàn)】

小史:回文的中心有可能是兩個(gè)字符中間铡原,這種情況沒(méi)有考慮到啊偷厦。

小史:

1商叹、先對(duì)字符串進(jìn)行預(yù)處理,兩個(gè)字符之間加上特殊符號(hào)#

2只泼、然后遍歷整個(gè)字符串剖笙,用一個(gè)數(shù)組來(lái)記錄以該字符為中心的回文長(zhǎng)度,為了方便計(jì)算右邊界请唱,我在數(shù)組中記錄長(zhǎng)度的一半(向下取整)

3弥咪、每一次遍歷的時(shí)候,如果該字符在已知回文串最右邊界的覆蓋下十绑,那么就計(jì)算其相對(duì)最右邊界回文串中心對(duì)稱的位置酪夷,得出已知回文串的長(zhǎng)度

4、判斷該長(zhǎng)度和右邊界孽惰,如果達(dá)到了右邊界晚岭,那么需要進(jìn)行中心擴(kuò)展探索。當(dāng)然勋功,如果第3步該字符沒(méi)有在最右邊界的“羽翼”下坦报,則直接進(jìn)行中心擴(kuò)展探索。進(jìn)行中心擴(kuò)展探索的時(shí)候狂鞋,同時(shí)又更新右邊界

5片择、最后得到最長(zhǎng)回文之后,去掉其中的特殊符號(hào)即可

理解了算法之后骚揍,小史的代碼寫起來(lái)也是非匙止埽快,不一會(huì)兒就寫好了:

PlalindromeString.java

/**

*@authorxiaoshi?on?2018/9/24.

*?Happy?Mid-Autumn?Festival

*/

publicclassPlalindromeString{

//?判斷一個(gè)字符串是否回文信不,算法中用不到了

@Deprecated

privatebooleanisPlalindrome(String?s){

intlen?=?s.length();

for(inti?=0;?i?<?len?/2;?i++)?{

if(s.charAt(i)?!=?s.charAt(len?-1-?i))?{

returnfalse;

}

}

returntrue;

}

//?預(yù)處理字符串嘲叔,在兩個(gè)字符之間加上#

privateStringpreHandleString(String?s){

StringBuffer?sb?=newStringBuffer();

intlen?=?s.length();

sb.append('#');

for(inti?=0;?i?<?len;?i++)?{

sb.append(s.charAt(i));

sb.append('#');

}

returnsb.toString();

}

//?尋找最長(zhǎng)回文字串

publicStringfindLongestPlalindromeString(String?s){

//?先預(yù)處理字符串

String?str?=?preHandleString(s);

//?處理后的字串長(zhǎng)度

intlen?=?str.length();

//?右邊界

intrightSide?=0;

//?右邊界對(duì)應(yīng)的回文串中心

intrightSideCenter?=0;

//?保存以每個(gè)字符為中心的回文長(zhǎng)度一半(向下取整)

int[]?halfLenArr?=newint[len];

//?記錄回文中心

intcenter?=0;

//?記錄最長(zhǎng)回文長(zhǎng)度

intlongestHalf?=

0;

for(int?i?=?0;?i?<?len;?i++)?{

//?是否需要中心擴(kuò)展boolean?needCalc?=?true;

//?如果在右邊界的覆蓋之內(nèi)if(rightSide?>?i)?{

//?計(jì)算相對(duì)rightSideCenter的對(duì)稱位置int?leftCenter?=?2*?rightSideCenter?-?i;

//?根據(jù)回文性質(zhì)得到的結(jié)論

halfLenArr[i]?=?halfLenArr[leftCenter];

//?如果超過(guò)了右邊界,進(jìn)行調(diào)整if(i?+?halfLenArr[i]?>?rightSide)?{

halfLenArr[i]?=?rightSide?-?i;

}

//?如果根據(jù)已知條件計(jì)算得出的最長(zhǎng)回文小于右邊界抽活,則不需要擴(kuò)展了if(i?+?halfLenArr[leftCenter]?<?rightSide)?{

//?直接推出結(jié)論

needCalc?=

false;

}

}

//?中心擴(kuò)展if(needCalc)?{

while(i?-?1?-?halfLenArr[i]?>=?0?&&?i?+?1+?halfLenArr[i]?<?len)?{

if(str.charAt(i?+?1?+?halfLenArr[i])?==?str.charAt(i?-?1-?halfLenArr[i]))?{

halfLenArr[i]++;

}

else{

break;

}

}

//?更新右邊界及中心

rightSide?=?i?+?halfLenArr[i];

rightSideCenter?=?i;

//?記錄最長(zhǎng)回文串if(halfLenArr[i]?>?longestHalf)?{

center?=?i;

longestHalf?=?halfLenArr[i];

}

}

}

//?去掉之前添加的#

StringBuffer?sb?=

newStringBuffer();

for(int?i?=?center?-?longestHalf?+?1;?i?<=?center?+?longestHalf;?i?+=?2)?{

sb.append(str.charAt(i));

}

returnsb.toString();

}

}

Main.java

/**

*?@author?lixin?on?2018/9/24.

*/

publicclassMain{

publicstaticvoidmain(String[]?args){

PlalindromeString?ps?=newPlalindromeString();

String[]?testStrArr?=newString[]?{

"abcdcef",

"adaelele",

"cabadabae",

"aaaabcdefgfedcbaa",

"aaba",

"aaaaaaaaa"

};

for(String?str?:?testStrArr)?{

System.out.println(String.format("原字串?:?%s",?str));

System.out.println(String.format("最長(zhǎng)回文串?:?%s",?ps.findLongestPlalindromeString(str)));

System.out.println();

}

}

}

運(yùn)行結(jié)果:

原字串?:?abcdcef

最長(zhǎng)回文串?:?cdc

原字串?:?adaelele

最長(zhǎng)回文串?:?elele

原字串?:?cabadabae

最長(zhǎng)回文串?:?abadaba

原字串?:?aaaabcdefgfedcbaa

最長(zhǎng)回文串?:?aabcdefgfedcbaa

原字串?:?aaba

最長(zhǎng)回文串?:?aba

原字串?:?aaaaaaaaa

最長(zhǎng)回文串?:?aaaaaaaaa

【時(shí)間空間分析】

擴(kuò)展閱讀

【面試現(xiàn)場(chǎng)】如何實(shí)現(xiàn)可以獲取最小值的棧硫戈?

【面試現(xiàn)場(chǎng)】如何在10億數(shù)中找出前1000大的數(shù)

【面試現(xiàn)場(chǎng)】為什么要分穩(wěn)定排序和非穩(wěn)定排序?

來(lái)源:互聯(lián)網(wǎng)偵察

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末下硕,一起剝皮案震驚了整個(gè)濱河市丁逝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梭姓,老刑警劉巖霜幼,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異誉尖,居然都是意外死亡罪既,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)萝衩,“玉大人,你說(shuō)我怎么就攤上這事没咙⌒梢辏” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵祭刚,是天一觀的道長(zhǎng)牌捷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)涡驮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮知允,結(jié)果婚禮上习劫,老公的妹妹穿的比我還像新娘。我一直安慰自己棒口,他們只是感情好寄月,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著无牵,像睡著了一般漾肮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茎毁,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天克懊,我揣著相機(jī)與錄音,去河邊找鬼七蜘。 笑死谭溉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的橡卤。 我是一名探鬼主播夜只,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蒜魄!你這毒婦竟也來(lái)了扔亥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谈为,失蹤者是張志新(化名)和其女友劉穎旅挤,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伞鲫,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粘茄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柒瓣。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡儒搭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芙贫,到底是詐尸還是另有隱情搂鲫,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布磺平,位于F島的核電站魂仍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拣挪。R本人自食惡果不足惜擦酌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菠劝。 院中可真熱鬧赊舶,春花似錦、人聲如沸赶诊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甫何。三九已至出吹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辙喂,已是汗流浹背捶牢。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留巍耗,地道東北人秋麸。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像炬太,于是被迫代替她去往敵國(guó)和親灸蟆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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