LeetCode 题目 118:杨辉三角

简介: LeetCode 题目 118:杨辉三角

作者介绍:10年大厂数据\经营分析经验,现任字节跳动数据部门负责人

会一些的技术:数据分析、算法、SQL、大数据相关、python,欢迎探讨交流

欢迎加入社区:码上找工作

作者专栏每日更新:

LeetCode解锁1000题: 打怪升级之旅

python数据分析可视化:企业实战案例

漫画版算法详解

python源码解读

程序员必备的数学知识与应用

题目描述

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。在杨辉三角中,每个数是它左上方和右上方的数的和。

杨辉三角解析

在这个详解中,我们将使用 ASCII 图形来说明杨辉三角的构建过程,包括逐行添加新的行的过程。这个图解可以帮助理解每一行是如何基于前一行构建的。

杨辉三角的构建过程

初始状态
  1. 开始时,杨辉三角是空的。
第1行
  1. 添加第一行,只有一个数字 1
1
第2行
  1. 第二行有两个 1,每个都位于行的边界。
1
1 1
第3行
  1. 第三行中间的数字是上一行两个相邻数字之和(1 + 1)。
1
 1 1
1 2 1
第4行
  1. 第四行,中间的两个数字分别是上一行相邻两数之和(1+2 和 2+1)。
1
   1 1
  1 2 1
 1 3 3 1
第5行
  1. 第五行,中间三个数字由上行相邻数字之和得到(1+3、3+3 和 3+1)。
1
     1 1
    1 2 1
   1 3 3 1
  1 4 6 4 1
总结过程
  • 杨辉三角的每一行都从 1 开始和结束。
  • 除了第一个和最后一个数字外,每个数字都是它正上方两个数字的和。
  • n 行(从 1 开始计数)有 n 个数字。

解题思路与算法

方法一:逐行构建
解题步骤:
  1. 初始化一个空列表 triangle 作为结果。
  2. 遍历从 0numRows-1 的每一行。
  3. 对于每一行,创建一个长度等于行号加一的新行,首尾元素设为1。
  4. 对于每一行的中间元素,按照杨辉三角的规则,由上一行的相邻两个元素求和得到。
  5. 将构建好的行添加到 triangle 中。
Python 代码示例
def generate(numRows):
    """生成杨辉三角的前numRows行"""
    triangle = []
    for row_num in range(numRows):
        row = [None for _ in range(row_num + 1)]
        row[0], row[-1] = 1, 1  # 第一个和最后一个元素始终为1
        for j in range(1, len(row) - 1):
            row[j] = triangle[row_num - 1][j - 1] + triangle[row_num - 1][j]
        triangle.append(row)
    return triangle
方法二:一行代码解
解题步骤:
  1. 使用列表推导式和递推公式直接生成杨辉三角的每一行。
  2. 利用 Python 的生成器语法简化代码实现。
Python 代码示例
def generate(numRows):
    """一行代码生成杨辉三角"""
    return [[1 if j == 0 or j == i else triangle[i-1][j-1] + triangle[i-1][j] for j in range(i+1)] for i in range(numRows)]
方法三:动态规划
解题步骤:
  1. 初始化一个空列表 triangle
  2. 从第一行到第 numRows 行,利用动态规划的思想,每一行基于前一行生成。
  3. 同样地,每行的首尾元素为1,其他元素由上一行的两个相邻元素相加得到。
  4. 每生成一行即存入 triangle
Python 代码示例
def generate(numRows):
    triangle = []
    for row_num in range(numRows):
        row = [1] * (row_num + 1)  # 每行元素初始化为1
        for j in range(1, row_num):
            row[j] = triangle[-1][j - 1] + triangle[-1][j]
        triangle.append(row)
    return triangle
方法四:使用递归
解题步骤:
  1. 定义递归函数,如果请求行数为1,返回只包含一行的杨辉三角。
  2. 否则,递归调用自身生成前 numRows - 1 行,然后基于最后一行计算新的一行,并添加到结果中。
Python 代码示例
def generate(numRows):
    if numRows == 1:
        return [[1]]
    else:
        result = generate(numRows - 1)
        last_row = result[-1]
        new_row = [1]
        for i in range(1, len(last_row)):
            new_row.append(last_row[i - 1] + last_row[i])
        new_row.append(1)
        result.append(new_row)
        return result
方法五:迭代改进版
解题步骤:
  1. 初始化一个包含第一行的列表。
  2. 迭代从第二行开始,每一行都通过上一行来计算。
  3. 使用临时列表存储当前行,计算完成后加入最终结果。
Python 代码示例
def generate(numRows):
    triangle = [[1]]
    for row_number in range(1, numRows):
        prev_row = triangle[-1]
        current_row = [1]
        for j in range(1, row_number):
            current_row.append(prev_row[j-1] + prev_row[j])
        current_row.append(1)
        triangle.append(current_row)
    return triangle

算法分析

  • 时间复杂度
  • 所有方法的时间复杂度基本为 (O(n^2)),其中 (n) 是行数。每行的计算成本大约与行号成正比。
  • 空间复杂度
  • 方法一、三、四和五:(O(n^2)),需要存储整个三角形。
  • 方法二:同样是 (O(n^2)),但因为使用了列表推导,可能有额外的内存开销。

不同算法的优劣势对比

  • 逐行构建(方法一)直观易理解,适合大多数初学者。
  • 一行代码解(方法二)代码简洁,但可能在理解和调试时较为复杂。
  • 动态规划(方法三)标准且易于理解,展示了动态规划思想的典型应用。
  • 使用递归(方法四)代码简洁,但对于大的行数可能导致调用栈溢出。
  • 迭代改进版(方法五)提供了介于方法一和方法三之间的解决方案,保持了代码的清晰性和执行的高效性。

应用示例

杨辉三角可以用于计算组合数学中的二项式系数,这在概率论、统计学和算法设计中非常有用。例如,它可以用来计算多项式展开的系数,或者在计算概率时快速找到相关的系数。在图形设计中,杨辉三角也被用于计算贝塞尔曲线等复杂图形的点。


欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
1月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目
|
2月前
|
SQL Oracle 关系型数据库
CASE WHEN 语句的语法及示例,LeetCode 题目 “确认率” 练习
本文介绍了SQL中CASE语句的两种形式和语法,并通过LeetCode题目“确认率”的SQL查询示例展示了CASE语句在实际问题中的应用,解释了如何使用CASE语句计算特定条件的比率。
|
3月前
|
算法
LeetCode第12题目整数转罗马数字
该文章介绍了 LeetCode 第 12 题整数转罗马数字的解法,通过使用 TreeMap 按照整数从大到小排序,先使用大的罗马数字表示整数,再用小的,核心是先表示完大的罗马数字,想通此点该题较简单。
LeetCode第12题目整数转罗马数字
|
3月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
50 6
|
3月前
|
算法
LeetCode第13题目罗马数字转整数
该文章介绍了 LeetCode 第 13 题罗马数字转整数的解法,通过从大到小解析罗马数字,根据罗马数字的特点,按照从大到小的顺序匹配罗马数字和整数的关系,从而解决该问题,同时强调要注意观察题目考查的知识点特征。
|
5月前
|
C语言
详解Leetcode中关于malloc模拟开辟二维数组问题,涉及二维数组的题目所给函数中的各个参数的解读
详解Leetcode中关于malloc模拟开辟二维数组问题,涉及二维数组的题目所给函数中的各个参数的解读
34 1
|
4月前
|
存储 算法
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
|
5月前
|
容器
【LeetCode刷题】栈和队列题目练习~
【LeetCode刷题】栈和队列题目练习~
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总(4)
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总