38、外觀數列 | 演算法(leetode,附思維導圖 + 全部解法)300題

碼農三少發表於2022-01-08

零 標題:演算法(leetode,附思維導圖 + 全部解法)300題之(38)外觀數列

碼農三少 ,一個致力於編寫極簡、但齊全題解(演算法)的博主

一 題目描述

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

二 解法總覽(思維導圖)

思維導圖

三 全部解法

1 方案1

1)程式碼:

// 方案1 “類似斐波那切數列,使用2個變數”

// 思路:
// 1)狀態初始化
// 2)迴圈處理 n-1 次,不斷處理 pre、now 值
// 2.1)根據 pre 值,計算出 now 值
// 2.2)將 now值 賦值給 pre 值,now 置為 '',接著進行下一次迴圈處理 ——> 根據 pre 值,計算出 now 值
// 3)返回結果 pre值 
var countAndSay = function(n) {
    // 1)狀態初始化
    let pre = '1',
        now = '';

    // 2)迴圈處理 n-1 次,不斷處理 pre、now 值
    for (let i = 0; i < n - 1; i++) {
        // 2.1)根據 pre 值,計算出 now 值
        const preLength = pre.length;
        let count = 1;
        for (let j = 0; j < preLength; j++) {
            if (pre[j] === pre[j + 1]) {
                count++;
            }
            else {
                now += count + '' + pre[j];
                count = 1;
            }
        }

        // 2.2)將 now值 賦值給 pre 值,now 置為 '',接著進行下一次迴圈處理 ——> 根據 pre 值,計算出 now 值
        pre = now;
        now = '';
    }

    // 3)返回結果 pre值 
    return pre;
}

2 方案2

1)程式碼:

// 方案2 “遞迴 - 普通法”
var countAndSay = function(n) {
    const dfs = (n) => {
        // 1)遞迴出口
        if (n === 1) {
            return '1';
        }

        // 2)遞迴主體
        return dfs(n-1).replace(/(\d)\1*/g, item =>`${item.length}${item[0]}`);
    };

    return dfs(n);
}

3 方案3

1)程式碼:

// 方案3 “遞迴 - 簡潔法”
var countAndSay = function(n) {
    if (n === 1) {
        return '1';
    }
    
    return countAndSay(n-1).replace(/(\d)\1*/g, item =>`${item.length}${item[0]}`);
}

4 方案4

1)程式碼:

// 方案4 “正則 + 迴圈法”

// 思路:
// 1)狀態初始化
// 2)迴圈處理:不斷結合正則匹配情況,使用 replace 函式對 resStr 進行更新
// 2.1)注(核心):'111221'.match(/(\d)\1*/g) ,輸出 ['111', '22', '1'] 
// 這樣看下面程式碼就容易很多了, item 依次為 '111', '22', '1' 。
// 3)返回結果 resStr 
var countAndSay = function(n) {
    // 1)狀態初始化
    let resStr = '1';

    // 2)迴圈處理:不斷結合正則匹配情況,使用 replace 函式對 resStr 進行更新
    for (let i = 1; i < n; i++){
        // 2.1)注(核心):'111221'.match(/(\d)\1*/g) ,輸出 ['111', '22', '1'] 
        // 這樣看下面程式碼就容易很多了, item 依次為 '111', '22', '1' 。
        resStr = resStr.replace(/(\d)\1*/g, item =>`${item.length}${item[0]}`);
    }

    // 3)返回結果 resStr 
    return resStr;
};

5 方案5

1)程式碼:

// 方案5 “JS裝X法:正則 + 遞迴 --> 1行程式碼”

// 思路:
// countAndSay(3) = countAndSay(2).replace(...)
//     = countAndSay(1).replace(...).replace(...)
//     = 1.replace(...).replace(...).replace(...)
var countAndSay = function(n) {
    // 注:理解如下注釋,程式碼就很容易了
    // countAndSay(3) = countAndSay(2).replace(...)
        // = countAndSay(1).replace(...).replace(...)
        // = 1.replace(...).replace(...).replace(...)
    return n == 1 ? '1' : countAndSay(n-1).replace(/(\d)\1*/g, item =>`${item.length}${item[0]}`);
};

相關文章