這是去一個小公司遇到的機試題,當時花了一個多小時寫完的,但是有很多細節沒考慮好,題目如下:
請您用Java語言實現兩個函數encode()和decode(),分別實現對字符串的變換和復原.變換函數encode()順序考察已知字符串的字符,按以下規則逐組生成新字符串:
(1)若已知字符串的當前字符不是大於0的數字字符,則複製該字符於新字符串中;
(2)若已知字符串的當前字符是一個數字字符,且它之後沒有後繼字符,則簡單地將它複製到新字符串中;
(3)若已知字符串的當前字符是一個大於0的數字字符,並且還有後繼字符,設該數字字符的面值爲n,則將它的後繼字符(包括後繼字符是一個數字字符)重複複製n+1次到新字符串中;
(4)以上述一次變換爲一組,在不同組之間另插入一個下劃線’_’用於分隔;
(5)若已知字符串中包含有下劃線’_’,則變換爲 ”\UL” 。
復原函數decode()做變換函數encode()的相反的工作.按照上述規則逆運算,變回原來的字符串。
例如:encode()函數對字符串24ab_2t2的變換結果爲 444_aaaaa_a_b_\UL_ttt_t_2
今天再寫就順暢多了,速度也快很多,先看encode()代碼如下:
public String encode(String str){
int len = str.length();
StringBuilder sb = new StringBuilder();
char c;// current char
char cnext;// next char
for(int i=0;i<len;i++){
c = str.charAt(i);
if((c<='0' || c>'9')&& c!='_'){// 判斷1
sb.append(c);
if(i!=(len-1)){
sb.append("_");
}
continue;// 當0是最後一位的時候,同時滿足了判斷1和判斷2,所以加上continue,防止重複拼接。
}
if(c>='0' && c<='9' && i==(len-1)){// 判斷2
sb.append(c);
if(i!=(len-1)){
sb.append("_");
}
}
if(c>'0' && c<='9' && i!=(len-1)){// 判斷3
cnext = str.charAt(i+1);
int c_int = c-48;
for(int j=0;j<=c_int;j++){
sb.append(cnext);
}
if(i!=(len-1)){
sb.append("_");
}
}
if('_'==c){// 判斷4
sb.append("\\UL");
if(i!=(len-1)){
sb.append("_");
}
}
}
return sb.toString();
}
要考慮到每個部分拼接後那個‘’作爲分隔符拼接上,並且在最後一個部分後不再拼接;對於“當前字符不是大於0的數字字符”,要把‘’也考慮進去,不然結果中會多出很多’_’;對於取出的每個char型的字符,有的需要轉換成int型,char的‘0’-‘9’減去48後就是對應的int型0-9的數字。
下面就是deCode()方法了,decode()方法逆向思考,不太好處理。代碼如下:
public String deCode(String str){
String[] parts = str.split("_");
int len = parts.length;
StringBuilder sb = new StringBuilder();
// 初始化StringBuilder
for(int k=0;k<len;k++){
sb.append("0");
}
String part;// parts數組的單個元素:part
int part_len;
char c;// part中的單個字符
// 遍歷parts的每個部分
for(int i=0;i<len;i++){
part = parts[i];
part_len = part.length();// part的長度
c = part.charAt(0);
if(part_len>1){
if(c>='0' && c<='9'){
sb.setCharAt(i, (char)(part_len-1+48));
sb.setCharAt(i+1, c);
}
if(!(c>='0' && c<='9') && c!='\\'){
sb.setCharAt(i, (char)((part_len-1)+48));
sb.setCharAt(i+1, c);
}
}else{
sb.setCharAt(i, c);
}
if("\\UL".equals(part)){
sb.setCharAt(i,'_');
}
}
return sb.toString();
}
decode()逆向思考比較難,我覺得先考慮就是將字符串split(),再對拆分出的每一部分進行解析:如果長度大於1,那麼就取出裏面的字符,逐個判斷處理;而長度不大於1,就是單個字符了;餘下的就是比較“\UL”了。