LeetCode刷题挑战-javascript:119.杨辉三角 II

135 阅读1分钟

R-C.jpeg 「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

题目

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex **行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

1626927345-DZmfxB-PascalTriangleAnimated2.gif

示例 1:

输入: rowIndex = 3

输出: [1,3,3,1]

示例 2:

输入: rowIndex = 0

输出: [1]

示例 3:

输入: rowIndex = 1

输出: [1,1]  

提示: 0 <= rowIndex <= 33  

进阶: 你可以优化你的算法到 O(rowIndex) 空间复杂度吗?

解题思路

方法一:DP

外层循环从上往下一层层求,复用一维数组 res(滚动数组),计算每个位置上的元素,只取决于上一行的值。

内层遍历的递推式为res[j] = res[j] + res[j-1],要保证等号右边的两个,是上一行的“旧值”。

如果内层遍历是从左往右,会出现res[j-1]是本行的上一轮迭代求出的新值,不是上一行的旧值。

所以,内层遍历的方向取从右往左。这样保证了计算新值时,等号右边都是旧值。

var getRow = function(rowIndex) {
    const res = new Array(rowIndex + 1);
    res[0] = 1;
    
    for (let i = 1; i < rowIndex + 1; i++) { 
        res[0] = res[i] = 1;
        for (let j = i - 1; j >= 1; j--) { 
            res[j] = res[j] + res[j - 1];
        }
    }
    return res;
};

方法二:递归(超时了)

定义递归函数:返回出第 i 行,第 j 列的元素值。

递归的公式是 cal(i,j) = cal(i-1, j-1) + cal(i-1, j)

递归的结束条件是:当 j == 0 || i == j,元素值为1,返回1,它其实就是 dp 的 base case。

var getRow = function(rowIndex) {
    const res = new Array(rowIndex + 1);
    for (let j = 0; j < rowIndex + 1; j++) { 
        res[j] = cal(rowIndex, j);
    }
    return res
};

var cal = function(i, j) {
    if (j == 0 || i == j) {
        return 1;
    }
    return cal(i-1, j-1) + cal(i-1, j);
}

当遇到 30 这个case 就超时了

方法三:记忆划递归

用一个二维数组memo,存计算过的子问题的结果,当遇到相同的递归子问题时,直接返回缓存值,避免落入重复的递归。

基于上面代码轻轻一改就有了如下

var getRow = function(rowIndex) {
    const memo = new Array(rowIndex + 1);
    for (let i = 0; i < memo.length; i++) { 
        memo[i] = new Array(i + 1);
    }
    for (let j = 0; j < rowIndex + 1; j++) { 
        memo[rowIndex][j] = cal(rowIndex, j, memo);
    }
    return memo[rowIndex]
};

var cal = function(i, j, memo) {
    if (j == 0 || i == j) {
        return 1;
    }
    if (memo[i][j] > 0) {
        return memo[i][j];
    }
    memo[i][j] = cal(i-1, j-1, memo) + cal(i-1, j, memo);
    
    return memo[i][j] 
}

结束语

这里是小葵🌻,只要把心朝着太阳的地方,就会有温暖~

让我们一起来攻克算法难关吧!!