力扣最热一百题——杨辉三角

目录

题目链接:118. 杨辉三角 - 力扣(LeetCode)

题目描述

示例

提示:

解法一:利用特性构建杨辉三角

1. 结果存储结构:

2. 初始化和循环遍历每一层:

3. 构建每一层:

4. 填充中间的元素:

5. 添加最后一个元素:

6. 将当前行添加到结果集:

7. 更新 len:

8. 返回最终结果:

Java写法:

C++写法:

运行时间

时间复杂度和空间复杂度

解法二:递归

递归思路:

Java写法:

C++写法:

关键变化:

运行时间

时间复杂度和空间复杂度

解法三:不讲武德版(面向测试用例编程)

Java写法:

运行时间

总结

解法总结:

小结:


题目链接:118. 杨辉三角 - 力扣(LeetCode)

注:下述题目描述和示例均来自力扣

题目描述

给定一个非负整数 numRows生成「杨辉三角」的前 numRows 行。

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

示例

示例 1:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例 2:

输入: numRows = 1
输出: [[1]]

提示:

  • 1 <= numRows <= 30

解法一:利用特性构建杨辉三角

1. 结果存储结构
  • 这里使用 List<List<Integer>> 来存储杨辉三角的每一行数据。res 是最终返回的结果集,它是一个二维列表,存放着每一层的数组。
2. 初始化和循环遍历每一层
  • len 代表当前层的元素个数。每一层的元素个数是递增的,从 1 开始。
  • numRows 是杨辉三角的行数,for 循环遍历每一行,numberOfLayers 代表当前的行索引(从 0 开始)。
3. 构建每一层
  • 每一行是一个 List<Integer>,并且我们首先将 1 加入到列表中,因为每一行的第一个元素总是 1
4. 填充中间的元素
  • 中间的元素是由上一行的相邻两个元素相加得到的。res.get(numberOfLayers - 1) 取得上一行的数据,然后 get(i) 取得上一行中第 i 个元素,get(i - 1) 取得上一行中第 i - 1 个元素,将它们相加,并将结果添加到当前行 one 中。
  • i1 开始,到 len - 2,因为第一个和最后一个元素已经加到 one 中了。
5. 添加最后一个元素
  • 除了第一行,所有的行最后一个元素都是 1,所以通过判断当前层是不是第一层来决定是否添加最后一个元素 1
6. 将当前行添加到结果集
  • 每次生成一行后,将它添加到 res 中。
7. 更新 len
  • 每次处理完一层后,len 增加 1,因为下一行的元素个数比当前行多一个。
8. 返回最终结果
  • 最终返回 res,即生成的完整杨辉三角。

Java写法:

class Solution {public List<List<Integer>> generate(int numRows) {// 定义出返回的结果集List<List<Integer>> res = new ArrayList<>();// 1// 1 1// 1 2 1// 1 3 3 1// 1 4 6 4 1// 那么其实我们把杨辉三角抽象到我们的二维数组(链表)中// 就是边上的数都是1,中间的数,是上一个数组中=>当前索引的数+前一个索引的数// 定义出 len 表示一层的数量 1,2,3...int len = 1;// numberOfLayers表示层数for(int numberOfLayers = 0; numberOfLayers < numRows; numberOfLayers++){// 记录一层的数据List<Integer> one = new ArrayList<>();one.add(1);int i = 1;for(;i < len - 1; i++){// 将两数相加再放入列表one.add(res.get(numberOfLayers - 1).get(i) + res.get(numberOfLayers - 1).get(i - 1));}if(numberOfLayers != 0){one.add(1);}res.add(one);len++;}return res;}
}

C++写法:

C++ 中没有 List 类型,通常使用 vector 来替代。同时,在 C++ 中我们也使用 vector<vector<int>> 来表示二维数组。代码结构与 Java 类似。

#include <vector>
using namespace std;class Solution {
public:vector<vector<int>> generate(int numRows) {// 定义返回的结果集vector<vector<int>> res;// numberOfLayers表示层数for (int numberOfLayers = 0; numberOfLayers < numRows; numberOfLayers++) {// 记录当前行的数据vector<int> one;one.push_back(1);  // 每行的第一个元素为1// 中间元素是上一行的相邻元素之和for (int i = 1; i < numberOfLayers; i++) {one.push_back(res[numberOfLayers - 1][i - 1] + res[numberOfLayers - 1][i]);}// 每行的最后一个元素为1(除了第一行)if (numberOfLayers > 0) {one.push_back(1);}// 将当前行添加到结果集res.push_back(one);}return res;}
};

运行时间

时间复杂度和空间复杂度

  • 时间复杂度

    • 外层循环遍历每一行,循环次数为 numRows,即 O(n)
    • 内层循环对每一行的元素进行处理,每一行最多有 numRows 个元素,最坏情况下是 O(n)
    • 因此,时间复杂度是 O(n^{2}),其中 n 是杨辉三角的行数。
  • 空间复杂度

    • 结果 res 存储了每一行的元素,空间复杂度为 O(n^{2}),即每一行的元素数量之和(1 + 2 + 3 + ... + n)是 O(n^{2})

 




解法二:递归

递归思路:

  1. 递归起始:初始时,杨辉三角的第一行 [1] 被添加到 list 中。
  2. 递归生成每一行
    • 每次递归调用都会生成当前行并添加到 list 中。
    • 当前行通过上一行的元素计算得出,首先是第一个 1,然后是中间的元素,通过相邻两个元素之和得出,最后是尾部的 1
  3. 递归终止:当生成的行数等于 numRows 时,停止递归。

Java写法:

class Solution {public List<List<Integer>> generate(int numRows) {// 初始化存储杨辉三角的二维列表List<List<Integer>> list = new ArrayList<>();// 初始化第一行 [1]List<Integer> arr = new ArrayList<>();arr.add(1);list.add(arr);// 如果只需要生成第一行,直接返回if(numRows == 1) return list;// 否则递归生成剩下的行method(numRows, list, arr);return list;}void method(int number, List<List<Integer>> list, List<Integer> arr){// 如果已经生成了所需的行数,则停止递归if(list.size() == number){return;}// 初始化新的一行List<Integer> newArr = new ArrayList<>();newArr.add(1);  // 每一行的第一个元素是1// 计算中间的元素,通过上一行相邻元素之和填充for(int i = 0; i < arr.size() - 1; i++) {newArr.add(arr.get(i) + arr.get(i + 1));}newArr.add(1);  // 每一行的最后一个元素是1list.add(newArr);  // 添加当前行到结果中// 递归生成下一行method(number, list, newArr);}
}

C++写法:

关键变化:

  1. vector 替换 List:C++ 中没有 List 类,改为使用 vector,这是 C++ 标准库中最常用的动态数组类型。
  2. push_back 替代 add:C++ 的 vector 使用 push_back() 方法来添加元素,替代 Java 中的 add() 方法。
  3. 引用传递:为了提高性能,method 函数中的 listarr 都采用了引用传递(vector<int>&vector<vector<int>>&),这样可以避免复制数据。

#include <vector>
using namespace std;class Solution {
public:vector<vector<int>> generate(int numRows) {// 初始化存储杨辉三角的二维向量vector<vector<int>> list;// 初始化第一行 [1]vector<int> arr = {1};list.push_back(arr);// 如果只需要生成第一行,直接返回if (numRows == 1) return list;// 否则递归生成剩下的行method(numRows, list, arr);return list;}private:void method(int number, vector<vector<int>>& list, vector<int>& arr) {// 如果已经生成了所需的行数,则停止递归if (list.size() == number) {return;}// 初始化新的一行vector<int> newArr = {1};  // 每一行的第一个元素是1// 计算中间的元素,通过上一行相邻元素之和填充for (int i = 0; i < arr.size() - 1; i++) {newArr.push_back(arr[i] + arr[i + 1]);}newArr.push_back(1);  // 每一行的最后一个元素是1list.push_back(newArr);  // 添加当前行到结果中// 递归生成下一行method(number, list, newArr);}
};

运行时间

        就离谱,测试用例比较有特点导致的,多跑几次可以遇到一次0ms 的情况,这种操作在力扣不是第一次出现了,居然比下面的不讲武德版本还快无语了

时间复杂度和空间复杂度

  • 时间复杂度O(n^2),生成杨辉三角时,生成每行的元素需要遍历前一行的元素,所以总时间复杂度为二次方。
  • 空间复杂度O(n^2),需要存储杨辉三角的所有行,每一行的元素个数是递增的,空间复杂度也是二次方。



解法三:不讲武德版(面向测试用例编程)

        这么搞笑的解法,在我看见只有

        这么点数据的时候我就发现了,非常抽象哈。

Java写法:

class Solution {public List<List<Integer>> generate(int numRows) {// 直接定义出来所有的数据集Integer[][] a= {{1},{1, 1},{1, 2, 1},{1, 3, 3, 1},{1, 4, 6, 4, 1},{1, 5, 10, 10, 5, 1},{1, 6, 15, 20, 15, 6, 1},{1, 7, 21, 35, 35, 21, 7, 1},{1, 8, 28, 56, 70, 56, 28, 8, 1},{1, 9, 36, 84, 126, 126, 84, 36, 9, 1},{1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1},{1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1},{1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1},{1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1},{1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1},{1, 15, 105, 455, 1365, 3003, 5005, 6435, 6435, 5005, 3003, 1365, 455, 105, 15, 1},{1, 16, 120, 560, 1820, 4368, 8008, 11440, 12870, 11440, 8008, 4368, 1820, 560, 120, 16, 1},{1, 17, 136, 680, 2380, 6188, 12376, 19448, 24310, 24310, 19448, 12376, 6188, 2380, 680, 136, 17, 1},{1, 18, 153, 816, 3060, 8568, 18564, 31824, 43758, 48620, 43758, 31824, 18564, 8568, 3060, 816, 153, 18, 1},{1, 19, 171, 969, 3876, 11628, 27132, 50388, 75582, 92378, 92378, 75582, 50388, 27132, 11628, 3876, 969, 171, 19, 1},{1, 20, 190, 1140, 4845, 15504, 38760, 77520, 125970, 167960, 184756, 167960, 125970, 77520, 38760, 15504, 4845, 1140, 190, 20, 1},{1, 21, 210, 1330, 5985, 20349, 54264, 116280, 203490, 293930, 352716, 352716, 293930, 203490, 116280, 54264, 20349, 5985, 1330, 210, 21, 1},{1, 22, 231, 1540, 7315, 26334, 74613, 170544, 319770, 497420, 646646, 705432, 646646, 497420, 319770, 170544, 74613, 26334, 7315, 1540, 231, 22, 1},{1, 23, 253, 1771, 8855, 33649, 100947, 245157, 490314, 817190, 1144066, 1352078, 1352078, 1144066, 817190, 490314, 245157, 100947, 33649, 8855, 1771, 253, 23, 1},{1, 24, 276, 2024, 10626, 42504, 134596, 346104, 735471, 1307504, 1961256, 2496144, 2704156, 2496144, 1961256, 1307504, 735471, 346104, 134596, 42504, 10626, 2024, 276, 24, 1},{1, 25, 300, 2300, 12650, 53130, 177100, 480700, 1081575, 2042975, 3268760, 4457400, 5200300, 5200300, 4457400, 3268760, 2042975, 1081575, 480700, 177100, 53130, 12650, 2300, 300, 25, 1},{1, 26, 325, 2600, 14950, 65780, 230230, 657800, 1562275, 3124550, 5311735, 7726160, 9657700, 10400600, 9657700, 7726160, 5311735, 3124550, 1562275, 657800, 230230, 65780, 14950, 2600, 325, 26, 1},{1, 27, 351, 2925, 17550, 80730, 296010, 888030, 2220075, 4686825, 8436285, 13037895, 17383860, 20058300, 20058300, 17383860, 13037895, 8436285, 4686825, 2220075, 888030, 296010, 80730, 17550, 2925, 351, 27, 1},{1, 28, 378, 3276, 20475, 98280, 376740, 1184040, 3108105, 6906900, 13123110, 21474180, 30421755, 37442160, 40116600, 37442160, 30421755, 21474180, 13123110, 6906900, 3108105, 1184040, 376740, 98280, 20475, 3276, 378, 28, 1},{1, 29, 406, 3654, 23751, 118755, 475020, 1560780, 4292145, 10015005, 20030010, 34597290, 51895935, 67863915, 77558760, 77558760, 67863915, 51895935, 34597290, 20030010, 10015005, 4292145, 1560780, 475020, 118755, 23751, 3654, 406, 29, 1}};// 装填数据集到我们的list集合之中List<List<Integer>> list = new ArrayList<>();for (int i = 0; i < numRows; i++) {list.add((List<Integer>)Arrays.asList(a[i]));}// 直接返回即可return list;}
}

运行时间

        没啥提升我是没有想到的,过于离谱了还是。


总结

解法总结:

  1. 解法一(迭代构建)

    • 使用二维数组 List<List<Integer>> 存储杨辉三角。
    • 从第一行 [1] 开始,逐行构建,每行的首尾元素为 1,中间的元素为上一行相邻两个元素之和。
    • 时间复杂度:O(n^2),空间复杂度:O(n^2)
  2. 解法二(递归构建)

    • 递归地生成每一行,通过上一行的元素计算当前行的值。
    • 时间复杂度:O(n^2),空间复杂度:O(n^2)
  3. 解法三(硬编码)

    • 直接定义一个二维数组,包含了杨辉三角的所有行。
    • 适用于测试用例数较少的情况,时间复杂度和空间复杂度均为常数级别。

小结:

  • 解法一和解法二通过动态计算逐行生成杨辉三角,适合处理较大的 numRows 值。
  • 解法三虽然效率较高,但不具通用性,只适用于有限的 numRows 值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/884871.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决com.mysql.jdbc.NonRegisteringDriver内存泄漏问题

1. 问题背景 线上出现内存报警&#xff0c;通过dump文件&#xff0c;MAT分析&#xff0c;发现mysql-connector-java 有内存泄漏问题 2.问题分析 然后看大对象列表&#xff0c;NonRegisteringDriver 对象确实占内存比较多&#xff0c;里面村的数据库连接的虚引用占比较多 3.解…

【AIGC】ChatGPT提示词Prompt高效编写技巧:逆向拆解OpenAI官方提示词

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;OpenAI官方提示词的介绍OpenAI官方提示词的结构与组成如何通过分析提示词找到其核心组件 &#x1f4af;OpenAI官方提示词分析案例一&#xff1a;制定教学计划案例二&…

Ubuntu 22 安装 Apache Doris 3.0.3 笔记

Ubuntu 22 安装 Apache Doris 3.0.3 笔记 1. 环境准备 Doris 需要 Java 17 作为运行环境&#xff0c;所以首先需要安装 Java 17。 sudo apt-get install openjdk-17-jdk -y sudo update-alternatives --config java在安装 Java 17 后&#xff0c;可以通过 sudo update-alter…

多线程生产消费者模型

线程同步 互斥锁(互斥量)条件变量生产/消费者模型 一、互斥锁 C11提供了四种互斥锁&#xff1a; mutex&#xff1a;互斥锁。timed_mutex&#xff1a;带超时机制的互斥锁。recursive_mutex&#xff1a;递归互斥锁。recursive_timed_mutex&#xff1a;带超时机制的递归互斥锁…

理解 WordPress | 第五篇:页面构建器选择指南

WordPress 专题致力于从 0 到 1 搞懂、用熟这种可视化建站工具。 第一阶段主要是理解。 第二阶段开始实践个人博客、企业官网、独立站的建设。 如果感兴趣&#xff0c;点个关注吧&#xff0c;防止迷路。 什么是 WordPress 构建器 WordPress 构建器&#xff08;Page Builder&am…

【Linux系统编程】第四十二弹---多线程编程全攻略:涵盖线程创建、异常处理、用途、进程对比及线程控制

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、线程创建 2、线程异常 3、线程用途 4、进程 VS 线程 5、线程控制 5.1、创建和等待线程 1、线程创建 线程能看到进程的大…

基于SSM的在线作业管理系统 -octopus-master(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。你想解决的问题&#xff0c;今天给大家介绍…

医学影像类和医用电气设备测试标准整理

医学影像类和医用电气设备测试标准整理 1、GB 9706.225-2022 医用电气设备 第2-25部分:心电图机的基本安全和基本性能专用要求 GB 9706.225规定了在201.3.63中定义的通过自身或作为ME系统一部分,提供可供诊断用的心电图报告的心电图机基本安全和基本性能,以下称为ME设备。 …

鸿蒙原生应用开发及部署:首选华为云,开启HarmonyOS NEXT App新纪元

目录 前言 HarmonyOS NEXT&#xff1a;下一代操作系统的愿景 1、核心特性和优势 2、如何推动应用生态的发展 3、对开发者和用户的影响 华为云服务在鸿蒙原生应用开发中的作用 1、华为云ECS C系列实例 &#xff08;1&#xff09;全维度性能升级 &#xff08;2&#xff…

3^100的位数判断

3^100的位数判断 问题来源 字节面试&#xff0c;面试官提问&#xff1a;口算估计3^100的位数&#xff0c;或是给出位数估计范围。 解决方案 方法一&#xff1a; 该方法纯口算&#xff0c;可得一个较为准确的一个范围 2 100 < 3 100 < 4 100 2^{100}<3^{100}<…

ROS2简介与Ubuntu24.04中安装指南

之前安装了一个版本&#xff0c;但是不愿意写blog&#xff0c;现在想想自己就是个沙子立个flag&#xff0c;每次配置项目&#xff0c;写流程blog ROS简介 ROS&#xff08;Robot Operating System&#xff09;是一个开源的机器人软件平台&#xff0c;提供了许多工具和库来帮助…

Linux sudo命令及权限设置

普通用户的权限是有限制的&#xff0c;需要更大的权限&#xff0c;就需要使用 root 用户&#xff0c;但又不想一直使用 root 用户&#xff0c;如普通用户查看 8080 端口的监听情况&#xff1a; netstat -tulnp | grep :8080 只能查看自己的 不想用 root 用户&#xff0c;继续…

微服务网关的认证管理;原理与实践

API安全认证是网关的最重要能力 API 网关为了保护对外提供的API&#xff0c;避免诸如恶意访问、未授权访问、应用漏洞及黑客攻击等导致的数据和资产损失&#xff0c;采用API网关的认证机制显得十分必要。 这种认证机制通过基于token的身份验证来实现&#xff0c;它允许应用程…

STM32 + CubeMX + 硬件SPI + W5500 +TcpClient

这篇文章记录一下STM32W5500TCP_Client的调试过程&#xff0c;实现TCP客户端数据的接收与发送。 目录 一、W5500模块介绍二、Stm32CubeMx配置三、Keil代码编写1、添加W5500驱动代码到工程&#xff08;添加方法不赘述&#xff0c;驱动代码可以在官网找&#xff09;2、在工程中增…

微信小程序中,点击视频,没有跳转播放,可能是因为没有在app.json中正确注册视频播放页面的路径

const customMethodMap {handlePreview(e) {const { item: { url } } e?.currentTarget?.datasetconsole.log(Clicked item URL:, url); // 输出URLconst type url.split(.)[url.split(.)?.length - 1]console.log(File type:, type); // 输出文件类型console.log(isDoc(…

软件体系结构

第一章 构件 具有某种功能的 可复用的软件结构单元,为组装服务,可部署,具有规范的接口规约和显式的语境依赖 构件模型 构件模型是对构件本质特征的抽象描述&#xff0c;可以把它想象成一个类的组合&#xff0c;它封装了多个类&#xff0c;并具有一个或多个服务而提供了简单…

Spark 的Standalone集群环境安装与测试

目录 一、Standalone 集群环境安装 &#xff08;一&#xff09;理解 Standalone 集群架构 &#xff08;二&#xff09;Standalone 集群部署 二、打开监控界面 &#xff08;一&#xff09;master监控界面 &#xff08;二&#xff09;日志服务监控界面 三、集群的测试 &a…

react的antd-mobile使用Steps显示物流

antd-mobile的图标&#xff0c;是需要安装依赖的 step如果只有一个步骤是不会展示的&#xff0c;代码里面的标题那块可以看出来 尝试了很多遍测试发现一直不显示&#xff0c;查询后发现是这个组件的本身设置的原因 那么就算你只展示一个那么也要写两个step&#xff0c;第二个…

基于鸟类AI识别的果园智能物联网解决方案

1. 项目背景 我国拥有广阔的果园种植面积&#xff0c;但每年因鸟类造成的损失高达数亿元。传统的防鸟害措施&#xff0c;如建立防护网和使用物理化学方法&#xff0c;效果并不理想&#xff0c;且成本较高。为了解决这一问题&#xff0c;深圳快瞳科技有限公司的提出基于鸟类AI识…

让Erupt框架支持.vue文件做自定义页面模版

Erupt是什么&#xff1f; Erupt 是一个低代码 全栈类 框架&#xff0c;它使用 Java 注解 动态生成页面以及增、删、改、查、权限控制等后台功能。 零前端代码、零 CURD、自动建表&#xff0c;仅需 一个类文件 简洁的注解配置&#xff0c;快速开发企业级 Admin 管理后台。 提…