「算法」LeetCode 605. 種花問題(JavaScript版)

老規矩,題目鏈接:https://leetcode-cn.com/problems/can-place-flowers/
這是一道簡單題,解題最重要的部分就是抽象,將問題的解抽象爲除法運算,求出兩個1之間的0的個數,-1/2並向下取整就能得到這兩個1之間可以種的花的數目,最後做判斷,即爲題解。
本人想到兩種解法,基本原理類似,如果別的小夥伴還有更好的解決辦法或是覺得我的方法不正確,歡迎大家在評論區提出來~

解法1:

export default (arr, n) => {
    let cnt = 0;
    let max = 0;
    let len = arr.length;
    // first中保存第一個1出現的下標
    let first = arr.indexOf(1);
    // last中保存最後一個1出現的下標
    let last = arr.lastIndexOf(1);
    // 核心算法:返回兩個1之間可以種的花的數目
    let MAX = (sum) => {
        return Math.floor((sum - 1) / 2);
    }
    // 記錄兩個1之間0的個數並求可以種的花的數目,加到max中
    for (let i = first + 1; i < last + 1; i++) {
        if (arr[i] === 0) {
            cnt++;
        } else {
            max += MAX(cnt);
            cnt = 0;
        }
    }
    if (first === -1) {
    	// 若數組全爲0,則可以種的花的數目直接由數組長度/2並向上取整
        max = Math.ceil(len / 2);
    } else {
    	// 若數組不全爲0,則需要考慮開頭和結尾可以種的花的數目,用開頭和結尾的0的個數/2並向下取整,加到max中
        max += (Math.floor(first / 2) + Math.floor((len - 1 - last) / 2));
    }
    // 判斷n是否小於或等於可種花的總數,是則返回true,否則返回false
    if (n <= max) {
        return true;
    } else {
        return false;
    }
}

解法1思路如下:
首先將數組arr頭部和尾部的0全部去掉,只計算第一個1和最後一個1之間可以種的花的數目(至於爲什麼要這樣做,因爲頭和尾的0只需要判斷一邊是否有1,而第一個1和最後一個1之間的0就需要判斷兩側是否有1),然後就是一個純數學問題,找規律,兩個1之間連續3個0就能種1朵花,連續5個0就能種2朵……以此類推,發現連續0的個數/2然後向下取整就能得到這兩個1之間可以種的花的數目,最後就能求得第一個1和最後一個1之間可以種的花的數目,然後再來計算首尾可以種的花的數目,求得總數max,與參數n做比較,如果n <= max則返回true,否則返回false,即爲題解。

解法2:

export default (arr, n) => {
    let max = 0;
    // 向數組的首尾都添加一個0
    arr.unshift(0);
    arr.push(0);
    // 遍歷整個數組
    for (let i = 1, len = arr.length; i < len - 1; i++) {
    	// 當下標爲i的元素爲0時,判斷其左右兩側是否爲0,是則計數器max++,且指針i++
        if (!arr[i]) {
            if (arr[i - 1] === 0 && arr[i + 1] === 0) {
                max++;
                // 這是一個縮短運行時長的方法,可有可無,不影響結果
                if (max === n) {
                    return true;
                }
                i++;
            }
        }
    }
    // 判斷n是否小於或等於可種花的總數,是則返回true,否則返回false
    return n <= max ? true : false;
}

解法2思路如下:
先將數組的首尾都補上一個0方便後面使用同樣的條件來判斷是否可以種下一朵花,然後遍歷整個數組,判斷下標爲i的元素是否爲0且左右兩側是否也爲0,是則計數器max++,且指針i++(爲什麼指針i還要自加一次?因爲確定該元素和其左右兩側元素都爲0後,右側的0就不能再填1了),最後求得總數max,與參數n做比較,如果n <= max則返回true,否則返回false,即爲題解。

小結:
這道題只要將問題成功抽象了,基本上就解出來了,但是這題裏面坑有點多,必須考慮數組首尾的0、數組元素全爲0以及數組只有1個元素的情況。

解題筆記:

  1. indexOf方法可以返回參數在數組中第一次出現的下標,同理lastIndexOf方法可以返回參數在數組中最後一個次出現的下標
  2. Math.ceil方法可以返回一個數向上取整的結果,Math.floor方法可以返回一個數向下取整的結果
  3. 解題過程中可以加入一些條件使得耗費時間減少
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章