算法導論:字符統計問題

  在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工具類」中,採用相似上述「判斷字符是否出現」,「保存字符出現次數」標誌量的方式處理平,閏年二月天數的選擇問題。翻譯

相關文章
相關標籤/搜索