一道面試題引發的思考
阿新 • • 發佈:2019-01-24
1.昨天(10月10日)騰訊一面,一道簡單的面試題,本以為寫得還不錯,結果今天回來仔細思考並coding,發現此程式中漏洞多多。
2.題意:刪除一個字串中重複出現的字元,只留下第一次出現的字元。如:輸入abaacdba,輸出abcd。
3.思路:定義一個數組來存放每個字元出現的次數,如果發現字元已經出現,則刪除該字元。
4.程式碼:
(1)當時寫的版本:
(2)當時檢查了一遍,發現沒有加 *ret = '\0'這一句,加上之後自以為還比較滿意。char* DeleteFun(char* str) { int times[WordNumber]; for (int i = 0; i < WordNumber; i++) { times[i] = 0; } char* p = str; int index; while (*p != '\0') { index = *p - 'a'; if (times[index] == 0) { times[index]++; } p++; } p = str; char* ret = str; while (*p != '\0') { index = *p - 'a'; if (times[index] != 0) { times[index] = 0; *ret = *p; ret++; } p++; } ret++; *ret = '\0'; return str; }
5.回來發現的問題
(1)最後ret++是多餘的,有錯的,加了這一句會多一個字元;
(2)時間花費了2*N,開銷有點大;
(3)這裡只考慮了26個小寫字母,而沒有考慮大寫字母和特殊字元。
6.剛剛仔細想想,並且在與kk同學的討論中,把程式改進了一下,如下:
幾點思考:char* DeleteFun1(char* str) { int times[256]; //memset(times, 0, 256 * sizeof(int)); memset(times, 0, sizeof(times)); char *p = str; char *q = str; while (*p != '\0') { if (times[*p] != 0) { p++; } else { times[*p] = 1; *q = *p; p++; q++; } } *q = '\0'; return str; }
(1)出現次數陣列大小為256,可以容納所有的大小寫字母和特殊字元;
(2)初始化使用memset,比用for迴圈效率高,而且寫得更簡單;
(3)只要用一個迴圈即可,即掃描的時候即判斷這個字元是否是出現了,如果沒有出現則留下這個字元,如果已經出現了則直接pass掉;
(4)不用加index這個變數,也不用做操作*p - 'a',可以直接用*p來作下標(因為開了256大小的陣列);
(5)sizeof(times)的大小和256 * sizeof(int)的大小是一樣的。