第一篇連結:字串類習題、面試題詳解(第一篇)
6題:迴文串(競賽基礎題)
輸入一個字串,求出其最長迴文子串。子串的含義是:在原串中連續出現的字串片段。迴文的含義是:正著看和倒著看相同,如abba和yyxyy。在判斷時,應該忽略所有標點符號和空格,且忽略大小寫,但輸出應保持原樣(在迴文串的首部和尾部不要輸出多餘字元)。輸入字串長度不超過5000,且佔據單獨一行。應該輸出最長的迴文串,如果有多個,輸出起始位置最靠左的。
樣例輸入:Confuciuss say: Madam, I’m Adam.
樣例輸出:Madam,I’m Adam
方法1:列舉迴文串的起點和終點。
1 #include <stdio.h> 2 #include <ctype.h> 3 #include <string.h> 4 #define MAXN 5000 + 10 5 6 char buf[MAXN], s[MAXN]; 7 int p[MAXN]; 8 9 int main(void) 10 { 11 int n, m = 0, max = 0, x = 0, y = 0; 12 int i, j, k, ok; 13 fgets(buf, sizeof(buf), stdin); 14 n = strlen(buf); 15 16 for (i = 0; i < n; i++) 17 { 18 if (isalpha(buf[i])) 19 { 20 p[m] = i; //儲存字元的實際位置 21 s[m++] = toupper(buf[i]); //儲存為大寫字母 22 } 23 } 24 25 for (i = 0; i < m; i++) //列舉迴文串起始位置 26 { 27 for (j = i; j < m; j++) //列舉迴文串終止位置 28 { 29 ok = 1; 30 for (k = i; k <= j; k++) 31 { 32 if (s[k] != s[i + j - k]) 33 ok = 0; 34 } 35 36 if (ok && j - i + 1 > max) 37 { 38 max = j - i + 1; 39 x = p[i]; 40 y = p[j]; 41 } 42 } 43 } 44 45 for (i = x; i <= y; i++) 46 { 47 printf("%c", buf[i]); 48 } 49 printf("\n"); 50 51 return 0; 52 }
方法2:列舉迴文串的中間位置。
1 #include <stdio.h> 2 #include <string.h> 3 #include <ctype.h> 4 #define MAXN 5000 + 10 5 char buf[MAXN], s[MAXN]; 6 int p[MAXN]; 7 8 int main(void) 9 { 10 int n, m = 0, max = 0, x = 0, y = 0; 11 int i, j; 12 fgets(buf, sizeof(buf), stdin); 13 n = strlen(buf); 14 15 for (i = 0; i < n; i++) 16 { 17 if (isalpha(buf[i])) 18 { 19 p[m] = i; //儲存字元實際位置 20 s[m++] = toupper(buf[i]); 21 } 22 } 23 24 for (i = 0; i < m; i++) //列舉迴文串的中間位置 25 { 26 for (j = 0; i - j >= 0 && i + j < m; j++) //迴文子串長度為奇數 27 { 28 if (s[i - j] != s[i + j]) 29 break; 30 if (j * 2 + 1 > max) 31 { 32 max = j * 2 + 1; 33 x = p[i - j]; 34 y = p[i + j]; 35 } 36 } 37 38 for (j = 0; i - j >= 0 && i + j + 1 < m; j++) //迴文串長度為偶數 39 { 40 if (s[i - j] != s[i + j + 1]) 41 break; 42 if (j * 2 + 2 > max) 43 { 44 max = j * 2 + 2; 45 x = p[i - j]; 46 y = p[i + j + 1]; 47 } 48 } 49 } 50 51 for (i = x; i <= y; i++) 52 printf("%c", buf[i]); 53 printf("\n"); 54 55 return 0; 56 }
解析:列舉迴文串的中間位置時要注意長度為奇數和偶數的處理方式是不一樣的。
7題:編碼實現求給定字串(全為小寫英文字母)的最小後繼,如"abc"的最小後繼為"abd","dhz"的最小後繼為"di"。(Google筆試題)
1 #include <stdio.h> 2 #include <string.h> 3 #define MAXN 1024 4 5 int main(void) 6 { 7 char buf[MAXN]; 8 int n, m, i; 9 scanf("%s", buf); 10 11 n = strlen(buf); 12 for (i = n - 1; i >= 0; i--) 13 { 14 if (buf[i] + 1 <= 'z') 15 { 16 buf[i] += 1; 17 buf[i + 1] = '\0'; 18 break; 19 } 20 } 21 printf("%s\n", buf); 22 23 return 0; 24 }
解析:對最後一個字元+1,如果大於'z'則對前一個字元+1,如果又大於 'z' 則重複之前的步驟。
8題:X86結構下,下面程式碼的printf輸出結果是什麼?(西艾面試題)
1 #include <stdio.h> 2 3 int main(void) 4 { 5 char str[20]="Good night"; 6 int *p = (int *)str; 7 p[0] = 0x61626364; 8 p[1] = 0x31323334; 9 p[2] = 0x41424344; 10 printf("%s\n", str); 11 12 return 0; 13 }
解析:輸出結果為:dcba4321DCBA。X86結構下,資料的低位儲存在記憶體的低地址中,資料的高位儲存在記憶體的高地址中。還需要注意常見字元的ASCII碼(十進位制),’a’為97,’A’為65,’1’為49。
9題:編一個函式,輸入一個字串,要求做一個新字串,把其中所有的一個或多個連續的空白字元都壓縮為一個空格。這裡所說的空白包括空格、'\t'、'\n'、'\r'。例如原來的字串是:
This Content hoho is ok
ok?
file system
uttered words ok ok ?
end.
壓縮了空白之後就是:
This Content hoho is ok ok? file systemuttered words ok ok ? end.(面試題)
參考程式如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 const char *p = "This Content hoho is ok\ 6 ok?\ 7 \ 8 file system\n\ 9 uttered words ok ok ?\ 10 end."; 11 12 int IsSpace(char c) 13 { 14 if (c == ' ') 15 return 1; 16 else if (c == '\n' || c == '\r') 17 return 2; 18 else if (c == '\t') 19 return 3; 20 else 21 return 0; 22 } 23 24 char *shrink_space(char *dest, const char *src, size_t n) 25 { 26 char *t_dest = dest; 27 char temp; 28 int pre = -1, cur = -1, key = -1; 29 while (IsSpace(*src)) //忽略字串起始空格 30 src++; 31 *t_dest = *src; 32 33 while ((temp = *src++) != '\0') 34 { 35 key = IsSpace(temp); 36 if (0 == key) //0表示字元 37 { 38 cur = 0; 39 *t_dest++ = temp; 40 } 41 else if (1 == key) //1表示空格 42 { 43 if (pre == 1) //如果前面也是空格 44 continue; 45 else 46 { 47 cur = 1; 48 *t_dest++ = temp; 49 } 50 } 51 else if (2 == key && pre == 0) 52 { 53 *t_dest++ = ' '; 54 } 55 else if (3 == key) 56 { 57 if (pre == 1) 58 continue; 59 else 60 { 61 *t_dest++ = ' '; //將\t轉換為1個空格 62 cur = 1; 63 } 64 } 65 pre = cur; 66 } 67 *t_dest = '\0'; 68 69 return dest; 70 } 71 int main(void) 72 { 73 int len = strlen(p); 74 char *dest = (char *)malloc(sizeof(char) * (len + 1)); 75 shrink_space(dest, p, 1); 76 printf("%s\n", dest); 77 free(dest); 78 dest = NULL; 79 80 return 0; 81 }
10題:寫出在母串中查詢子串出現次數的程式碼。(面試題)
1 #include <stdio.h> 2 #include <string.h> 3 #define BUFSIZE 1024 4 5 int StrCount(char *strLong, char *strShort) 6 { 7 int result = 0; 8 char *t_strS = strShort; 9 char *t_strD = strLong; 10 while (*t_strD != '\0') 11 { 12 t_strS = strShort; //子串 13 while (*t_strD == *t_strS && *t_strS != '\0' && *t_strD != '\0') 14 { 15 t_strD++; 16 t_strS++; 17 } 18 if (*t_strS == '\0') 19 result += 1; 20 else if (*t_strD == '\0') 21 break; 22 else 23 t_strD++; 24 } 25 26 return result; 27 } 28 29 int main(void) 30 { 31 int len; 32 char strD[BUFSIZE], strS[BUFSIZE]; 33 fgets(strD, sizeof(strD), stdin); 34 len = strlen(strD); 35 strD[len - 1] = '\0'; 36 fgets(strS, sizeof(strS), stdin); 37 len = strlen(strS); 38 strS[len - 1] = '\0'; 39 printf("%d\n", StrCount(strD, strS)); 40 return 0; 41 }