閱讀理解類面試題 : 一維生物

目錄

題目

題目解讀

解題


朋友遇到的題目,分享一波。侵刪~

這個題目的難點就在於讀題,如果題目讀明白了,問題自然就解決了。所以在看題的時候要耐心,需要發現除文字描述以外的信息。題目如下

題目

想象一種一維生物,由一系列順序排列的細胞構成(可以理解爲一維數組),細胞只有兩種狀態:活躍或者休眠(取值1或者0)。每經過一代進化,細胞狀態都會發生改變。細胞進化後狀態由當前該細胞狀態和左右相鄰細胞的狀態決定。三個細胞最多有2×2×2=2^3=8種狀態,在這8種狀態下進化後的結果代表一種規則。例如:

上面這類規則表示當前細胞狀態爲休眠且相鄰細胞狀態爲休眠時(000),當前細胞進化後狀態爲休眠(0);當前細胞休眠,左鄰居休眠,右鄰居活躍時(001),進化後狀態爲活躍(1);……;當前細胞活躍,左右鄰居都活躍(111),進化後爲休眠(0).

用8個bit表示的十進制數爲規則編號,總共有0-255共256個規則,例如:

請寫個程序,輸出給定規則編號N下,該生物前K輪的進化狀態。(假設生物的初始狀態固定,且只有最中間一個細胞爲活躍)

class Solution {
    public List<String> printStates(int N, int K) {

    }
}

例:

30號規則的進化過程如圖所示。

還請讀到這裏的親自己先嚐試理解題目,去儘量多的收集規律和信息。

 

題目解讀

想要看懂這個題目的重點就在於題目和樣例中給的三幅圖。首先看第一幅

從圖片和題目的描述我們可以知道,每一個方框內有四個小格子(狀態位),黑色代表該位是1,白色代表該位是0;上排三個連續的格子爲當前狀態位,表示當前自己和前後鄰居當前狀態,下邊單獨的格子爲衍生位,表示在當前狀態位是某個值的時候,下一次自己衍生出來是0還是1。

第二幅圖給出了幾個規則關係。

每一個rule代表了一種衍生關係,從讀題的感覺來看,我們需要在這幅圖中找到規律來知道rule0 ~ rule126的排列關係。自己觀察後,確實發現了規律:

給出的所有rule中,當前狀態位的排列都是固定的,都是「“111”,“110”,“101”,“100”,“011”,“010”,“001”,“000”」,而規則編號比如rule30,剛好是將八個格子看成是八個bit後,對應位 置1後得到30,00011110 = 2+4+8+16 = 30;其他規則也同樣遵循這個規律。那可想而知,rule0就是00000000,rule1就是00000001,以此類推。

 

解題

讀題到這裏,就可以開始構思解題思路了。主要分兩步:1- 構建規則映射; 2- 循環進化得到結果。

題目中描述會給定兩個int值,n代表規則num,k代表迭代輪數。那麼首先我們要通過n構建出一個代表規則的字典,然後讓給定的初始數組按照規則字典進化。

因爲key是固定的「“111”,“110”,“101”,“100”,“011”,“010”,“001”,“000”」,規則字典只需要找到n對應的那幾位爲1即可。代碼如下:

    public static Map<String,String> generateRule(int n){
        //按照從最低位到最高位的順序排列
        String [] values = new String[] {"000","001","010","011","100","101","110","111"};

        Map<String,String > rule = new HashMap<>();
        for (int i = 0;i < 8;i++){
            if ((n & (1 << i)) == 0){
                rule.put(values[i],"0");

            }else {
                rule.put(values[i],"1");
            }
        }

        return rule;
    }

一共八位所以循環八次,用1左移0位同n做與運算,如果得到是0,則n的第0位是0,如果結果大於0,則該位爲1.

得到規則映射後,進入進化階段:

    public static List<String> printStates(int n,int k){

        List<String> result = new ArrayList<>();
        Map<String,String> rule = generateRule(n);
        String [] current = new String[31];
        String  [] help = new String[31];

        //set default values
        for (int i = 0; i < current.length; i++){
            if (i == 15){
                current[i] = "1";
            }else {
                current[i] = "0";
            }
        }
        result.add(Solution.toString(current));
        String varifyValue = "";
        for (int j = 0; j < k;j++){
            for (int i = 0; i < current.length; i++){
                if (i == 0){
                    varifyValue = current[current.length - 1] + current[0] + current[i + 1];
                }else if (i == current.length - 1){
                    varifyValue = current[i - 1]+ current[i] + current[0];
                }
                else {
                    varifyValue = current[i - 1] + current[i] + current[i + 1];
                }
                help[i] = rule.get(varifyValue);

            }
            current = help.clone();
            result.add(Solution.toString(help));
        }

        return result;
    }

    public static String  toString(String [] strs){
        String res = "";
        for (String s : strs){
            res += s;
        }
        return res;
    }

進化階段需要注意的就是邊界值了,從樣例圖中可以看到,第一個一維生物的進化是以最後一個單位作爲左鄰居的,而最後一個一維生物是以第一個單位作爲右鄰居的(請回看題目樣例中的規則和衍生結果),除了這兩種情況以爲,每次的key等於前中後的組合值作爲key去rule map中取值即可。每次迭代的結果存放到List中等待返回。

最終代碼運行結果截圖和樣例對比如下

跟同事聊的過程中同事點撥,當前狀態位中的「“111”,“110”,“101”,“100”,“011”,“010”,“001”,“000”」就是7 ~ 0的二進制排列。

這道題目的實現難度可以說幾乎沒有,但是在面試的緊張狀態下很好的理解題目,從給出的信息中挖掘文字描述之外的信息,這方面考的很好了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章