題目:輸入乙個字串,輸出該字串中對稱的子字串的最大長度。比如輸入字串「google」,由於該字串裡最長的對稱子字串是「goog」,因此輸出4。
分析:可能很多人都寫過判斷乙個字串是不是對稱的函式,這個題目可以看成是該函式的加強版。
要判斷乙個字串是不是對稱的,不是一件很難的事情。我們可以先得到字串首尾兩個字元,判斷是不是相等。如果不相等,那該字串肯定不是對稱的。否則我們接著判斷裡面的兩個字元是不是相等,以此類推。基於這個思路,我們不難寫出如下**:
// whether a string between pbegin and pend is symmetrical?
bool issymmetrical(char* pbegin, char* pend)
if(pbegin == null || pend == null || pbegin > pend)
return false;
while(pbegin < pend)
if(*pbegin != *pend)
return false;
pbegin++;
pend --;
return true;
要判斷乙個字串pstring是不是對稱的,我們只需要呼叫issymmetrical(pstring, &pstring[strlen(pstring) – 1])就可以了。
現在我們試著來得到對稱子字串的最大長度。最直觀的做法就是得到輸入字串的所有子字串,並逐個判斷是不是對稱的。如果乙個子字串是對稱的,我們就得到它的長度。這樣經過比較,就能得到最長的對稱子字串的長度了。於是,我們可以寫出如下**:
// get the longest length of its all symmetrical substrings
// time needed is o(t^3)
int getlongestsymmetricallength_1(char* pstring)
if(pstring == null)
return 0;
int symmeticallength = 1;
char* pfirst = pstring;
int length = strlen(pstring);
while(pfirst < &pstring[length - 1])
char* plast = pfirst + 1;
while(plast <= &pstring[length - 1])
if(issymmetrical(pfirst, plast))
int newlength = plast - pfirst + 1;
if(newlength > symmeticallength)
symmeticallength = newlength;
plast++;
pfirst++;
return symmeticallength;
我們來分析一下上述方法的時間效率。由於我們需要兩重while迴圈,每重迴圈需要o(n)的時間。另外,我們在迴圈中呼叫了issymmetrical,每次呼叫也需要o(n)的時間。因此整個函式的時間效率是o(n3)。
通常o(n3)不會是乙個高效的演算法。如果我們仔細分析上述方法的比較過程,我們就能發現其中有很多重複的比較。假設我們需要判斷乙個子字串具有aaa的形式(a是aaa的子字串,可能含有多個字元)。我們先把pfirst指向最前面的字元a,把plast指向最後面的字元a,由於兩個字元相同,我們在issymtical函式內部向後移動pfirst,向前移動plast,以判斷a是不是對稱的。接下來若干步驟之後,由於a也是輸入字串的乙個子字串,我們需要再一次判斷它是不是對稱的。也就是說,我們重複多次地在判斷a是不是對稱的。
造成上述重複比較的根源在於issymmetrical的比較是從外向裡進行的。在判斷aaa是不是對稱的時候,我們不知道a是不是對稱的,因此需要花費o(n)的時間來判斷。下次我們判斷a是不是對稱的時候,我們仍然需要o(n)的時間。
如果我們換一種思路,我們從裡向外來判斷。也就是我們先判斷子字串a是不是對稱的。如果a不是對稱的,那麼向該子字串兩端各延長乙個字元得到的字串肯定不是對稱的。如果a對稱,那麼我們只需要判斷a兩端延長的乙個字元是不是相等的,如果相等,則延長後的字串是對稱的。因此在知道a是否對稱之後,只需要o(1)的時間就能知道aaa是不是對稱的。
我們可以根據從裡向外比較的思路寫出如下**:
// get the longest length of its all symmetrical substrings
// time needed is o(t^2)
int getlongestsymmetricallength_2(char* pstring)
if(pstring == null)
return 0;
int symmeticallength = 1;
char* pchar = pstring;
while(*pchar != '\0')
// substrings with odd length
char* pfirst = pchar - 1;
char* plast = pchar + 1;
while(pfirst >= pstring && *plast != '\0' && *pfirst == *plast)
pfirst--;
plast++;
int newlength = plast - pfirst - 1;
if(newlength > symmeticallength)
symmeticallength = newlength;
// substrings with even length
pfirst = pchar;
plast = pchar + 1;
while(pfirst >= pstring && *plast != '\0' && *pfirst == *plast)
pfirst--;
plast++;
newlength = plast - pfirst - 1;
if(newlength > symmeticallength)
symmeticallength = newlength;
pchar++;
return symmeticallength;
由於子字串的長度可能是奇數也可能是偶數。長度是奇數的字串是從只有乙個字元的中心向兩端延長出來,而長度為偶數的字串是從乙個有兩個字元的中心向兩端延長出來。因此我們的**要把這種情況都考慮進去。
在上述**中,我們從字串的每個字串兩端開始延長,如果當前的子字串是對稱的,再判斷延長之後的字串是不是對稱的。由於總共有o(n)個字元,每個字元可能延長o(n)次,每次延長時只需要o(1)就能判斷出是不是對稱的,因此整個函式的時間效率是o(n2)
對稱子字串的最大長度
題目 輸入乙個字串,輸出該字串中對稱的子字串的最大長度。比如輸入字串 google 由於該字串裡最長的對稱子字串是 goog 因此輸出4。方法 1.值得注意的是,回文的2種形式,aba,abba 1.對於aba的形式,從字串中的每乙個位置i,像兩邊擴充套件一位如果a i 1 a i 1 那麼繼續擴充...
對稱子字串的最大長度
題目 輸入乙個字串,輸出該字串中對稱的子字串的最大長度。比如輸入字串 google 由於該字串裡最長的對稱子字串是 goog 因此輸出4。方法 1.值得注意的是,回文的2種形式,aba,abba 1.對於aba的形式,從字串中的每乙個位置i,像兩邊擴充套件一位如果a i 1 a i 1 那麼繼續擴充...
對稱子字串的最大長度
題目 輸入乙個字串,輸出該字串中對稱的子字串的最大長度。比如輸入字串 google 由於該字串裡最長的對稱子字串是 goog 因此輸出4。author administrator public class main 判斷字串是否為對稱的,首位同時進行比較,時間複雜度為o n 是從兩端向中間靠齊進行的...