119. 杨辉三角 II

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
在这里插入图片描述
在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

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

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

我的思路

迭代法

前面2行直接生成,第三行(nowIndex = 2)在上一个结果,即[1,1]的倒数第二个位置插入2即可。

第4行及以后(nowIndex >= 3)的计算方法:都是在上一次结果的基础上进行修改。

  1. 第一个和最后一个元素保持不变,都是1。
  2. 第二个元素到倒数第三个元素,采用递推公式:当前位置的新值 = 上一次结果前一个位置的值+上一次结果当前位置的值,写成公式,就是 res.get(j) = res.get(j - 1) + res.get(j); 。但是直接在程序上这样写是不行的,因为我是直接在原来的结果上进行修改。这样做,第一次没问题,第二次及以后,需要利用上一轮计算结果位置原来的值,由于上次的的结果res.get(j)已经被修改了,因此计算结果就会出错。因此,需要设置2个变量second 和 first来分别提前存储当前位置(j)和上一个位置的值(j-1),这样就没问题了。
  3. 倒数第2个元素采用插入法,需要用到first变量。

迭代法程序(Java)

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> res = new ArrayList<>();
        res.add(1);
        if(rowIndex == 0)   return res;	// 返回第一行[1]
        res.add(1);
        if(rowIndex == 1)   return res;	// 返回第二行[1,1]
        
        for(int i = 2; i <= rowIndex; i++){
            int j = 1; 
            int first = res.get(0), second = 0;   // first 初始化为res的第一个值        
            // ***** 下面的 if 和 for 语句代码块的内容只有当 i >= 3 时才会执行
            if(i >= 3){	// 当 i >= 3 时,才做下面的处理
                j++;    
                first = res.get(1);	// first 修改为res的第2个值
                second = res.get(2);	// first 修改为res的第3个值
                res.set(1, res.get(0) + res.get(1));                
            }                       
            for(; j < i - 1; j++){	// 只有当 i >= 3 才有可能进入for循环
                res.set(j, first + res.get(j));
                // first 用于计算,second用于提前保存下一个用于计算的值,避免因上一行的计算而被覆盖掉
                first = second;	
                second = res.get(j + 1);
            }
            // ***** 当 i = 2 时,上面2个代码块不执行,只执行下面这个语句
            res.add(j, first + res.get(j));	// 在最后一个数字 1 前面插入对应的数字
        }
        return res;
    }
}

公式法

参考windliang的【解法二 公式法】,以及评论,我对原作者的程序做了一点修改,程序如下。测试了一下,其实原来的公式法程序还更快一点。

公式法程序(Java)

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> ans = new ArrayList<>();
        int N = rowIndex;
        long pre = 1;
        ans.add(1);
        for (int k = 1; k <= N/2; k++) {	// 用公式只计算一半的内容
            long cur = pre * (N - k + 1) / k;
            ans.add((int) cur);
            pre = cur;
        }
        for(int k = N/2 + 1; k <= N; k++){ // 剩下的内容,对称的位置复制过来即可
            ans.add(ans.get(N - k));            
        }
        return ans;
    }
}

更多思路可参考:windliang

如有不当之处,欢迎读者批评指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值