解--頭條的算法面試題-圓環開關燈

1 看看題目

PS:一個下午和晚上才完成這道題,雖然知道面試不可能有這麼多的時間,仍是抑制不住興奮跟你們分享一下,歡迎提提改善意見。

bVboxvT?w=1148&h=1080

1.1題幹分析

一、這是個圓環,因此沒有邊界,要處理好數組的邊界問題。
二、100個燈泡,燈的數量是確定的,這數組的長度能夠保證。
三、開關燈規則,觸發一個燈的開關會影響旁邊2個燈(取反)。
四、要全部燈泡都亮,那麼最後一次觸發確定是3個連續暗的燈泡在一塊兒的狀況。javascript

2 解題

2.1知足題乾的開關燈規則

// 開關燈,實現圓環的開關燈邏輯,注意處理一下數組的邊界狀況便可
function trigger(index, list) {
    var len = list.length;
    if(index>=len) {
        index = index -len
    }
    // 左邊
    var left = index - 1;
    left = left >= 0 ? left : len - 1;

    // 右邊
    var right = index + 1;
    right = right >= len ? right - len : right;

    list[left] = !list[left];
    list[index] = !list[index];
    list[right] = !list[right];
    return list
}

2.2解題算法

說明:java

  1. 註釋中,0表示暗,1表示亮。
  2. 算法複雜度爲n。
// 註釋中,0表示暗,1表示亮。
function init(list) {
    var len = list.length;
    /*
    * 一、算法難度爲n
    * 二、循環一遍,遇到暗燈就利用規則在下個位置觸發開關燈,不考慮對後面的影響,由於會循環到
    * */
    for (var i = 0; i < len; i++) {
        if(!list[i]){
            list = trigger(i+1, list)
        }
    }

    /*
    * 循環結束後,最後可能出現4種狀況(索引0-1,1表示亮,0表示滅):00,01,10,11
    * 將前3狀況預處理成(..0100...)的模式,咱們要處理成..000...的狀況,最後將燈點亮
    * Forward的index 是0100中的00的起始索引位置,請記住進入Forward時,list最後3個暗燈是0100的排列的
    * */
    if(!list[0]&&!list[1]){            //  001111...
        list = trigger(2,list)  //  010011...
        return Forward(2,list)
    } else if(!list[0]&&list[1]) {     //  0111111...
        list = trigger(1,list)  //  1001111...
        list = trigger(3,list)  //  1010011...
        return Forward(3,list)
    } else if(list[0]&&!list[1]) {     //  101111111...
        list = trigger(2,list)  //  110011111...
        list = trigger(4,list)  //  110100111...
        return Forward(4,list)
    } else {
        return list
    }
}

/*
* 最後1次開燈要爲連續的3個暗燈(即000,其他爲1),才能讓全部燈都亮了,它就是作這件事的。
* 讓0100中的00繞一圈到左邊來=>0001=>所有點亮了
* */
function Forward(index, list, num) {
    num = num ? +num : 0
    var len = list.length
    var i0 = (index + 2) >= len ? index + 2 - len : index + 2;
    var i1 = (index + 3) >= len ? index + 3 - len : index + 3;
    // 防止死循環,正常狀況不會超過list.length次的遞歸。
    if(num > list.length*1000) {
        return console.error("Forward 可能出現死循環!")
    }
    // 若是第3個位置是1就繼續偏移
    if(list[i0]){
        // 這樣的操做能夠將連續的00的位置偏移3
        list = trigger(index+1,list)
        list = trigger(i1,list)

        return Forward(i1,list, num+1)
    } else {
        return trigger(index+1,list)
    }
}

3 測試

3.1 測試準備

  1. 寫了一個隨機生成數組的方法,來隨機生成亮暗隨機的100個燈。
function getData(num) {
    var list = [];
    for(var i = 0; i< num; i++){
        list[i] = Math.random() > 0.5 ? true : false
    }
    return list
}
  1. 寫了個校驗最終結果的方法,100個值看不過來。
function auth(list) {
    console.log(list);
    var status = true;
    for(var i =0; i<list.length;i++){
        if(!list[i]) {
            status = false
            break;
        }
    }
    if(status) {
        console.log("success:檢驗經過")
    } else {
        console.error("error:檢驗不經過");
    }
}

3.2 測試

var data = getData(100)
// console.log(JSON.parse(JSON.stringify(data)))
auth(init(data))

3.3 測試結果,沒進黑盒。

在線看: https://codepen.io/FreadChen/...

clipboard.png

相關文章
相關標籤/搜索