5

38、外观数列 | 算法(leetode,附思维导图 + 全部解法)300题

 2 years ago
source link: https://segmentfault.com/a/1190000041246387
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

零 标题:算法(leetode,附思维导图 + 全部解法)300题之(38)外观数列

码农三少 ,一个致力于编写极简、但齐全题解(算法)的博主

一 题目描述

题目描述
题目描述
题目描述

二 解法总览(思维导图)

思维导图

三 全部解法

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;
}

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);
}

1)代码:

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

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;
};

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]}`);
};

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK