1. 程式人生 > >騰訊面試演算法題——編碼

騰訊面試演算法題——編碼

題目描述
假定一種編碼的編碼範圍是a ~ y的25個字母,從1位到4位的編碼,如果我們把該編碼按字典序排序,形成一個數組如下: a, aa, aaa, aaaa, aaab, aaac, … …, b, ba, baa, baaa, ab, baac … …, yyyw, yyyx, yyyy 其中a的Index為0,aa的Index為1,aaa的Index為2,以此類推。 編寫一個函式,輸入是任意一個編碼,輸出這個編碼對應的Index.
輸入描述:
輸入一個待編碼的字串,字串長度小於等於100.
輸出描述:
輸出這個編碼的index
示例1
輸入
baca
輸出
16331

首先分析題目,發現編碼其實是一個數組,陣列大小為25的四次方。但是程式碼構建一個數組會有空間限制的問題,構建完成之後再遍歷查詢得到編碼又會有時間複雜度的問題。所以這種方式不建議選取。仔細觀察這個陣列,發現有一定的規律。a開頭的所有編碼佔用了連續的一段陣列空間(其他字母同理),所以由聯想到樹。然後先構建一個由25棵樹組成的森林,根節點分別為a、b、c…y,每棵樹都是高度為3的滿25叉樹,子節點分別為a、b、c…y。如下圖所示(有些b與y之間忘了打省略號請忽略)。

從第一棵樹的根節點開始至各個節點的路徑便為編碼順序,以第一棵樹為例為a、aa、aaa、aaaa、aaab…ayyy,緊接第二棵樹為b、ba、baa、baaa……byyy,最終達到yyyy。這樣我們便得到了下面開始聯絡題目。以baca為例,編碼即為根節點為b的樹和其子節點a及下一層子節點c及再下一層子節點a所組成路徑的左側節點個數(包括b、a、c、a四個節點)減一(因為a的編碼為0)。如下圖所示。
這時候,問題就由求解編碼,變為了計算這條線左端所有節點的個數和。我們假設輸入字串為S0S1S2S3共計四個字元。那麼第一層的個數和便為:S0 - 'a' + 1第二層個數和為:(S0 - 'a')* 25^1 + (S1 - 'a' + 1)第三層個數和為:(S0 - 'a')* 25^2 + (S1 - 'a') * 25^1 + (S2 - 'a' + 1)第四層個數和為:(S0 - 'a')* 25^3 + (S1 - 'a') * 25^2 + (S2 - 'a') * 25^1 + (S3 - 'a' +1)計算過程中注意判斷S1、S2、S3是否存在,不存在時將對應的小的計算塊置為0。廢話少說,下面上程式碼(考慮到擴充套件性,增加了size變數,表示題目中規定的編碼字串最大長度)。
import java.util.*;
import java.math.*;

public class Main{
    public static void main(String[] args){
        Main object = new Main();
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
        	String s = sc.nextLine();
            int index = object.encode(s, 4);
            if(index < 0){
            	System.out.println("輸入資料格式有誤");
            }else{
            	System.out.println(index);
            }
        }
        sc.close();
    }

    public int encode(String s, int size){
    	int index = -1;
    	int length = s.length();
    	if(length == 0 || length > size){
    		return index;
    	}
    	for(int i = 0; i < length; i++){
    		if(s.charAt(i) < 'a' || s.charAt(i) > 'y'){
    			return index;
    		}
    	}
    	
    	index = 0;
    	for(int i = 0; i < size; i++){
    		for(int j = 0; j <= i; j++){
    			if(j < length){
    				if(i == j){
    					index += s.charAt(j) - 'a' + 1;
    				}else{
    					index += (s.charAt(j) - 'a') * Math.round(Math.pow((double)25, (double)(i - j)));
    				}
    			}
    		}
    	}
    	
        return index - 1;
    }
}