2125、銀行中的鐳射束數量 | 演算法(leetode,附思維導圖 + 全部解法)300題

碼農三少發表於2022-02-19

零 標題:演算法(leetode,附思維導圖 + 全部解法)300題之(2125)銀行中的鐳射束數量

一 題目描述

題目描述
題目描述
題目描述

二 解法總覽(思維導圖)

思維導圖

三 全部解法

1 方案1

1)程式碼:

// 方案1 “直接計數 - 模擬法”。

// 思路:
// 1)狀態初始化:map存放每一層存放 安全裝置 的情況。

// 2)核心1:遍歷 bank 的每一層。
// 2.1)遍歷當前層的每一列。
// 2.1.1)若 i層的j列 為 安全裝置,則 通過map、對 相應的值進行 +1 操作。

// 3)核心2:2層遍歷。
// 3.1)若 當前i、j 層均存在安全裝置 且 介於(i, j)層 均無安全裝置,
// 則 resCount += (map.get(i) * map.get(j)) 。

// 4)返回結果 resCount 。
var numberOfBeams = function(bank) {
    // isValid方法:介於 top、bottom 均沒有安全裝置,說明是 “合法的”。
    const isValid = (top, bottom, map) => {
        let resBool = true;

        for (let i = top + 1; i < bottom; i++) {
            if (map.get(i)) {
                resBool =  false;
                break;
            }
        }

        return resBool;
    };

    // 1)狀態初始化:map存放每一層存放 安全裝置 的情況。
    const l = bank.length;
    let map = new Map(),
        resCount = 0;

    // 2)核心1:遍歷 bank 的每一層。
    for (let i = 0; i < l; i++) {
        const tempStr = bank[i],
            tempStrLength = tempStr.length;
        
        // 2.1)遍歷當前層的每一列。
        for (let j = 0; j < tempStrLength; j++) {
            // 2.1.1)若 i層的j列 為 安全裝置,則 通過map、對 相應的值進行 +1 操作。
            if (tempStr[j] === '1') {
                if (map.has(i)) {
                    map.set(i, map.get(i) + 1);
                }
                else {
                    map.set(i, 1);
                }
            }
        }
    }

    // 3)核心2:2層遍歷。
    for (let i = 0; i < l; i++) {
        for (let j = i + 1; j < l; j++) {
            // 3.1)若 當前i、j 層均存在安全裝置 且 介於(i, j)層 均無安全裝置,
            // 則 resCount += (map.get(i) * map.get(j)) 。
            if (map.get(i) && map.get(j) && isValid(i, j, map)) {
                resCount += (map.get(i) * map.get(j));
            }
        }
    }

    // 4)返回結果 resCount 。
    return resCount;
};

2 方案2

1)程式碼:

// 方案2 “簡約的1次遍歷法”。

// 思路:
// 1)狀態初始化:pre = 0, resCount = 0 。

// 2)核心1:從 [0, l-1] 遍歷 bank 的每一層 。
// 2.1)獲得當前 i層 的安全裝置個數。
// 2.2)若 當前 i層 的安全裝置個數 大於 0,則 resCount += pre * cur; pre = cur 。

// 3)返回結果 resCount 。
var numberOfBeams = function(bank) {
    // getCountByLevel方法:獲取 bank的level層 的安全裝置個數。
    const getCountByLevel = (level) => {
        const tempStr = bank[level],
            tempStrLength = tempStr.length;
        let resNum = 0;

        for (let i = 0; i < tempStrLength; i++) {
            if (tempStr[i] === '1') {
                resNum++;
            }
        }

        return resNum;
    };

    // 1)狀態初始化:pre = 0, resCount = 0 。
    const l = bank.length;
    let pre = 0,
        resCount = 0;

    // 2)核心:從 [0, l-1] 遍歷 bank 的每一層 。
    for (let i = 0 ; i < l; i++) {
        // 2.1)獲得當前 i層 的安全裝置個數。
        const cur = getCountByLevel(i);
        // 2.2)若 當前 i層 的安全裝置個數 大於 0,則 resCount += pre * cur; pre = cur 。
        if (cur > 0) {
            resCount += pre * cur;
            pre = cur;
        }
    }

    // 3)返回結果 resCount 。
    return resCount;
}

3 方案3

1)程式碼:

// 方案3 “4行程式碼(因為有4個分號) - 裝X法”。
// n個元素 變成 1個元素 ---> 優先考慮陣列的 reduce 方法。

// 思路:
// 1)通過 陣列的 map 方法,計算 bank的每層安全裝置個數 —— 依次存放入陣列(“假定其名為 tempList ”)中,
// 2)通過 陣列的 reduce 方法,不斷根據 當前層的安全裝置個數(cur)、更新 當前鐳射束的總數量(acc) 並返回 。
var numberOfBeams = function(bank) {
    let pre = 0;

    return bank.map(item => item.split('').filter(itemInner => itemInner === '1').length)
        .reduce((acc, cur) => {
            if (cur > 0) {
                // 注:這1行 等同於 下面2行程式碼。
                [acc, pre] = [acc + (pre * cur), cur];
                // acc += pre * cur;
                // pre = cur;
            }
            return acc;
        }, 0);
}

四 資源分享 & 更多

1 歷史文章 - 總覽

歷史文章 - 總覽

刷題進度 - LeetCode:430 / 2520 、《劍指offer》:66 / 66

2 博主簡介

碼農三少 ,一個致力於編寫 極簡、但齊全題解(演算法) 的博主。
專注於 一題多解、結構化思維 ,歡迎一起刷穿 LeetCode ~

相關文章