在ACM之家看到一道有趣的算法題,好多相似華爲,Google等IT巨鱷,都以此爲模板來考察實習生。html
(1)華爲的考題形式是:經過鍵盤輸入一串小寫字母(a~z)組成的字符串,編寫一個字符串過濾程序,若字符串中出現多個相同的字符,將非首次出現的字符過濾掉。如,輸入字符串「abacacde」,則輸出的過濾結果爲「abcde」。面試
不是很難的問題,採用枚舉法,一個二重循環就可搞定。示例代碼以下:算法
1 package org.warnier.zhang.demo; 2 3 public class StringFilter { 4 5 public String filter(String origin) { 6 String result; 7 if (origin == null) { 8 result = null; 9 } else { 10 char[] chars = origin.toCharArray(); 11 StringBuilder sb = new StringBuilder(); 12 13 for (int i = 0; i < chars.length; i++) { 14 int j = 0; 15 for (; j < i; j++) { 16 if (chars[i] == chars[j]) { 17 break; 18 } 19 } 20 if (j == i) { 21 sb.append(chars[i]); 22 } 23 } 24 result = sb.toString(); 25 } 26 return result; 27 } 28 }
官網給出的解決方案更巧妙,以下翻譯爲了Java版:app
1 public String filter(String origin){ 2 String result; 3 if(origin == null){ 4 result = null; 5 }else{ 6 /** 7 * 判斷字符是否出現的標誌; 8 */ 9 boolean[] flags = new boolean[26]; 10 for(int i = 0; i < flags.length; i++){ 11 flags[i] = false; 12 } 13 char[] chars = origin.toCharArray(); 14 StringBuilder sb = new StringBuilder(); 15 /** 16 * 判斷字符是否第一次出現; 17 */ 18 for(int i = 0; i < chars.length; i ++){ 19 if(false == flags[chars[i] - 'a']){ 20 flags[chars[i] - 'a'] = true; 21 sb.append(chars[i]); 22 } 23 } 24 result = sb.toString(); 25 } 26 return result; 27 }
(2)Google的考題形式是:在一個字符串中找到第一個只出現一次的字符,如輸入abaccdeff,則輸出b。工具
若是提早參見過華爲面試的實習生是否是就要幸運的多了,在沒有算法複雜度的要求下,上面的代碼簡單修改一下就搞定了。如, post
1 public String filter(String origin) { 2 String result = null; 3 if (origin != null) { 4 char[] chars = origin.toCharArray(); 5 for (int i = 0; i < chars.length; i++) { 6 for (int j = 0; j < i; j++) { 7 if (chars[i] == chars[j]) { 8 chars[i] = '0'; 9 chars[j] = '0'; 10 break; 11 } 12 } 13 } 14 for (int i = 0; i < chars.length; i++) { 15 if (chars[i] != '0') { 16 result = String.valueOf(chars[i]); 17 break; 18 } 19 } 20 } 21 return result; 22 }
官網也給出了一種全新的解法,翻譯爲Java版以下:ui
1 public String filter(String origin){ 2 String result = null; 3 if(origin != null){ 4 /** 5 * 保存字符出現的次數; 6 */ 7 int[] flags = new int[26]; 8 for(int i = 0; i < flags.length; i++){ 9 flags[i] = 0; 10 } 11 /** 12 * 統計字符出現的次數; 13 */ 14 char[] chars = origin.toCharArray(); 15 for(int i = 0; i < chars.length; i++){ 16 flags[chars[i] - 'a']++; 17 } 18 for(int i = 0; i < flags.length; i++){ 19 if(flags[i] == 1){ 20 result = String.valueOf((char)('a' + i)); 21 break; 22 } 23 } 24 } 25 return result; 26 }
其實,官網給出的答案不難看出與上面華爲考題解答的類似處。這從另外一個角度說明,這道考題雖然華爲,Google的考察角度不一樣,可是萬變不離其宗,解題的過程當中要撥開迷霧,看清本質。spa
再者,官網的解題策略也是一種巧妙的思路,我曾在本身的一篇博客「分享:GenericCalendar工具類」中,採用相似上述「判斷字符是否出現」,「保存字符出現次數」標誌量的方式處理平,閏年二月天數的選擇問題。翻譯