算法小白的进阶之路(力扣1~5)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
前言
本栏目将记录博主暑假从0开始刷力扣的算法题,每一条题目我都会把知识点抽丝剥茧地进行分析,以便大家更好的理解和学习,话不多说,肝!
序号 | 标题 | 力扣序号 |
1 | 杨辉三角I | 118 |
2 | 杨辉三角II | 119 |
3 | 移动零 | 283 |
4 | 区域和检索 -数组不可变 | 303 |
5 | 第三大的数 | 414 |
1.杨辉三角I
题目:
给定一个非负整数 numRows
,生成「杨辉三角」的前 numRows
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
解题思路:
杨辉三角的性质: 每个位置上的数等于它上方两个数之和。
代码(go)
func generate(numRows int) [][]int {ans := make([][]int, numRows)for i := range ans {ans[i] = make([]int, i+1)ans[i][0] = 1ans[i][i] = 1for j := 1; j < i; j++ {ans[i][j] = ans[i-1][j] + ans[i-1][j-1]}}return ans
}
下面是代码的具体解析
行初始化:
ans[i] = make([]int, i+1)
创建一个长度为i+1
的数组,用于存储第i
行的元素。边界处理:
ans[i][0] = 1
:第一个元素始终为1,因为每行的开头和结尾都是1。ans[i][i] = 1
:最后一个元素也为1,因为杨辉三角每一行的首尾都是1。中间元素计算:
- 对于每一行的中间元素,即
1
到i-1
之间的元素,通过上一行对应位置的元素相加得到。具体计算公式为ans[i][j] = ans[i-1][j-1] + ans[i-1][j]
。这里利用了杨辉三角的性质:每个位置上的数等于它上方两个数之和。返回结果: 返回完成填充的二维数组
ans
,其中包含了从第0行到第numRows-1
行的所有元素。
j
从 1
开始,因为杨辉三角每一行的首尾元素都是 1
,不需要重新计算。
2.杨辉三角II
题目:
给定一个非负索引 rowIndex
,返回「杨辉三角」的第 rowIndex
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
方式一:递推
解题思路:
杨辉三角的性质: 每个位置上的数等于它上方两个数之和。
此题和上面那道杨辉三角解法类似,区别就是此题rowIndex是索引,所以需要+1
代码(go):
func getRow(rowIndex int) []int {C := make([][]int, rowIndex+1)for i := range C {C[i] = make([]int, i+1)C[i][0], C[i][i] = 1, 1for j := 1; j < i; j++ {C[i][j] = C[i-1][j-1] + C[i-1][j]}}return C[rowIndex]
}
方式二:
利用滚动数组进行优化
解题思路:
注意到对第 i+1 行的计算仅用到了第 i 行的数据,因此可以使用滚动数组的思想优化空间复杂度。
优化后的代码只需要计算两行的杨辉三角即可,可以节省内存空间
代码(go)
func getRow(rowIndex int) []int {var pre, cur []intfor i := 0; i <= rowIndex; i++ {cur = make([]int, i+1)cur[0], cur[i] = 1, 1for j := 1; j < i; j++ {cur[j] = pre[j-1] + pre[j]}pre = cur}return pre
}
代码解析:
pre
:前一行的数组。cur
:当前行的数组,随着每一行的生成而更新。cur[j] = pre[j-1] + pre[j]
:根据杨辉三角的性质,当前行的第j
列的值等于上一行的第j-1
列和第j
列的和。pre = cur
:将当前行cur
赋给pre
,作为下一行的基础。
方式三:
只用一个数组,进一步优化
解题思路:
我们使用一维数组,然后从右向左遍历每个位置。
每个位置的元素res[j] += 其左边的元素 res[j−1]。 row[j] += row[j-1]
第0行只有1
第1行刚刚开始是1,根据公式得出 11
第2行刚刚开始是11,,根据公式111 ---> 121
第3行刚刚开始是121,根据公式121--->1211--->1231--->1331
以此类推
为啥不从左向右遍历呢?因为如果从左向右遍历,那么左边的元素已经更新为第 i 行的元素了,而右边的元素需要的是第 i−1 行的元素。故从左向右遍历会破坏元素的状态。
代码(go)
func getRow(rowIndex int) []int {row := make([]int, rowIndex+1)row[0] = 1for i := 1; i <= rowIndex; i++ {for j := i; j > 0; j-- {row[j] += row[j-1]}}return row
}
3.移动零
题目:
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 :
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
解题思路:
此题运用到双指针的思路,设置两个指针,a依次向右遍历,b记录非零元素的位置,当a遇到0,则跳过,继续向右遍历,遇到非0的元素则交换ab的值,并且b向右前进一步。
即遍历的时候每遇到一个 非0 元素就将其往数组左边挪,第一次遍历完后,b指针的下标就指向了最后一个 非0 元素下标。
第二次遍历的时候,起始位置就从 b开始到结束,将剩下的这段区域内的元素全部置为 0。
这个思路类似于快速排序,可以去小破站看一下视频
快速排序
(图片出自王尼玛)
代码(java)
class Solution {public void moveZeroes(int[] nums) {if(nums==null) {return;}//第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j]int j = 0;for(int i=0;i<nums.length;++i) {if(nums[i]!=0) {nums[j++] = nums[i];}}//非0元素统计完了,剩下的都是0了//所以第二次遍历把末尾的元素都赋为0即可for(int i=j;i<nums.length;++i) {nums[i] = 0;}}
}
这道题花费了我两小时的时间,因为我先了解了快速排序的原理,然后再学习了双指针的思想,最后卡到的最简单自增自减运算符上...
注意:
for
循环的设计就是先执行循环体内的代码,然后再递增计数器
所以其实在 for(int i=0;i<nums.length;++i) 这段语句中 无论是++i,还是i++都是可以运行的。
然后在 nums[j++] = nums[i]这段语句中,其实j是先执行,然后再修改值的。以第二次循环为例,当i = 1的时候,遇到非0的元素,所有i 和 j 要交换元素 所以就是 num[0] = num[1] 然后j++ 变成1
4.区域和检索 -数组不可变
题目:
给定一个整数数组
nums
,处理以下类型的多个查询:
- 计算索引
left
和right
(包含left
和right
)之间的nums
元素的 和 ,其中left <= right
实现
NumArray
类:
NumArray(int[] nums)
使用数组nums
初始化对象int sumRange(int i, int j)
返回数组nums
中索引left
和right
之间的元素的 总和 ,包含left
和right
两点(也就是nums[left] + nums[left + 1] + ... + nums[right]
)
示例 :
输入: ["NumArray", "sumRange", "sumRange", "sumRange"] [[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]] 输出: [null, 1, -1, -3]
解题思路:
这里用到前缀和思想,可以理解为高中学的数列
我们可以画一个sum[0]到sum[6]的数列,以【2,5】为例(此处的2,5是索引值)
所以就是sum[6]-sum[2]
示例中的数组有6个元素,假如要计算索引2到5之间的总和(包含2到5),我们可以先计算索引为数组开始到5的总和减去数组开始到索引为2(不能包含索引2)
代码(java)
class NumArray {int[] sums;public NumArray(int[] nums) {int n = nums.length;sums = new int[n + 1];for (int i = 0; i < n; i++) {sums[i + 1] = sums[i] + nums[i];}}public int sumRange(int i, int j) {return sums[j + 1] - sums[i];}
}
5.第三大的数
题目:
给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。
示例 1:
输入:[3, 2, 1] 输出:1 解释:第三大的数是 1 。
示例 2:
输入:[1, 2] 输出:2 解释:第三大的数不存在, 所以返回最大的数 2 。
示例 3:
输入:[2, 2, 3, 1] 输出:1 解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。 此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。
方式一:
Set 去重 + 排序
解题思路:
先使用 Set
对重复元素进行去重,然后对去重后的元素进行排序,并返回第三大的元素。
代码(Java)
class Solution {public int thirdMax(int[] nums) {Set<Integer> set = new HashSet<>();for (int x : nums) set.add(x);List<Integer> list = new ArrayList<>(set);Collections.sort(list);return list.size() < 3 ? list.get(list.size() - 1) : list.get(list.size() - 3); }
}
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
使用一个增强型for循环遍历数组nums
,将每个元素添加到set
中。
for (int x : nums) set.add(x);
假如数组为【1,2,3】,那么执行
return list.size() < 3 ? list.get(list.size() - 1) : list.get(list.size() - 3);
这里的 list.size() - 3
实际上是 3 - 3 = 0
,而 list.get(0)
会返回列表中的第一个元素,即 1
。
方式二:
有限变量 + 遍历
解题思路:(大家可以参考一下宫水三叶的解析)
经典的找数组次大值的做法是使用两个变量 a 和 b 分别存储遍历过程中的最大值和次大值。
假设当前遍历到的元素为 x,当满足如下条件时,考虑更新 a 或者 b:
当 x>a 时,说明最大值被更新,同时原来的最大值沦为次大值。即有 b=a;a=x;
在条件 1 不满足,且有x>b 时,此时可以根据是否有「严格次大值」的要求,而决定是否要增加 x<a 的条件:
不要求为「严格次大值」:直接使用 x 来更新 b,即有 b=x;
当要求为「严格次大值」: 此时需要满足 x<a 的条件,才能更新 b。
回到本题,同理我们可以使用 a、b 和 c 三个变量来代指「最大值」、「严格次大值」和「严格第三大值」。从前往后遍历 nums,假设当前元素为 x,对是否更新三者进行分情况讨论(判断优先级从上往下):
1. x>a,说明最大值被更新,将原本的「最大值」和「次大值」往后顺延为「次大值」和「第三大值」,并用 x 更新 a;
2. x<a 且 x>b,说明次大值被更新,将原本的「次大值」往后顺延为「第三大值」,并用 x 更新 b;
3. x<b 且 x>c,说明第三大值被更新,使用 x 更新 c。
起始时,我们希望使用一个足够小的数来初始化 a、b 和 c,因此需要使用 long 来进行代替。返回时,通过判断第三大值是否为初始化时的负无穷,来得知是否存在第三大值。
代码(Java)
class Solution {long INF = (long)-1e18;public int thirdMax(int[] nums) {long a = INF, b = INF, c = INF;for (int x : nums) {if (x > a) {c = b; b = a; a = x;} else if (x < a && x > b) {c = b; b = x;} else if (x < b && x > c) {c = x;}}return c != INF ? (int)c : (int)a;}
}
❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
相关文章:

算法小白的进阶之路(力扣1~5)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…...

昇思25天学习打卡营第22天|MindSporeK基于Diffusion扩散模型学习- Diffusion与其他生成模型
Diffusion扩散模型 本文基于Hugging Face:The Annotated Diffusion Model一文翻译迁移而来,同时参考了由浅入深了解Diffusion Model一文。 本教程在Jupyter Notebook上成功运行。如您下载本文档为Python文件,执行Python文件时,请…...

【C++版本】protobuf与gRPC
文章目录 一、Protobuf二、安装以及使用protoc三、gRPC1.Q&A2.学习版rpc3.gRPC压缩算法 参考 一、Protobuf Google Protocol Buffers(protobuf)是一种语言中立、平台中立的序列化协议,旨在高效地将结构化数据进行序列化和反序列化。它主要…...

要抓住国际白银现货行情 以下这几点需要注意
国际白银现货行情最近表现不甚稳定,在七月上旬出现了比较强势的上涨,但随后出现强势的下跌,跌破了30关口。如果我们要抓住国际白银现货行情,那么以下这几点我们就需要注意。 一,建立交易计划,并且按计划执行…...

【计算机毕业设计】720图书馆智能选座系统
🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板ÿ…...

java面向对象重点总结
文章目录 java面向对象重点总结类与实例构造方法方法重载属性与修饰符封装继承多态重构抽象类接口抽象类和接口的区别:集合泛型 java面向对象重点总结 对象是一个自包含的实体,用一组可识别的特性和行为来标识。 面向对象编程,英文叫Object…...
1321:【例6.3】删数问题(Noip1994)
大模拟 #include<bits/stdc.h> using namespace std; int s,len; char c[245]; int main(){cin>>c>>s;//读入高精度数和待删除的数lenstrlen(c);//1、寻找第一个下降序列的转折点,删去//2、如果找不到,意味着全部递增,删…...

使用 Python 中的 ELSER 进行Serverless 语义搜索:探索夏季奥运会历史
作者:来自 Elastic Essodjolo Kahanam 本博客介绍如何使用语义搜索以自然语言表达形式从 Elasticsearch 索引中获取信息。我们将创建一个无服务器 Elasticsearch 项目,将之前的奥运会数据集加载到索引中,使用推理处理器和 ELSER 模型生成推理…...

[HITCON 2017]SSRFme 1
目录 代码审计 符号shell_exec() 函数:GET " . escapeshellarg($_GET["url"]):pathinfo($_GET["filename"]basename() 题目解析 代码审计 118.182.186.90 <?phpif (isset($_SERVER[HTTP_X_FORWARDED_FOR])) {$http_x_headers explod…...

看不见的硝烟:中国网络安全三十年沉浮史
2022 年 5 月 16 日,俄罗斯黑客组织 KillNet 向包括美国、英国、德国在内 10 个国家的政府正式 “宣战”。 2022 年 4 月 28 日,一则消息刷屏,北京健康宝在使用高峰期间,遭受到境外网络攻击。北京健康宝保障团队进行了及时有效应…...

3.7.物体检测算法
物体检测算法 1.R-CNN 首先使用启发式搜索算法来选择锚框,使用预训练模型对每个锚框抽取特征,训练一个SVM来对类别分类,最后训练一个线性回归模型来预测边缘框偏移。 R-CNN比较早,所以使用的是SVM 1.1 兴趣区域(RoI)池化…...

Spring源码解析(27)之AOP的核心对象创建过程2
一、前言 我们在上一节中已经介绍了Advisor的创建过程,当时我们创建的logUtil这bean,他在 resolveBeforeInstantiation返回的是null,那么就会继续往下执行doCreateBean方法。 二、源码分析 protected Object doCreateBean(String beanName,…...

【题解】【数学】—— [CSP-J 2023] 小苹果
【题解】【数学】—— [CSP-J 2023] 小苹果 [CSP-J 2023] 小苹果题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 1.题意分析2.代码 [CSP-J 2023] 小苹果 前置知识:数学分组思想,整体思想。 [CSP-J 2023] 小苹果 题目描述 小 Y 的桌子上…...

python实现微信聊天图片DAT文件还原
完整代码如下: from glob import glob import os from tqdm import tqdmdef get_sign(dat_r):signatures [(0x89, 0x50, 0x4e), (0x47, 0x49, 0x46), (0xff, 0xd8, 0xff)]mats [".png", ".gif", ".jpg"]for now in dat_r:for j, x…...
栈与队列——1.有效的括号
力扣题目链接 给定一个只包括 (,),{,},[,] 的字符串,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。注意空字符串可被认为是有效…...
C语言家教记录(二)
C语言家教记录(二) 导语输入输出表达式算数运算符示例程序赋值运算符简单赋值复合赋值 总结和复习 导语 本次授课内容如下:输入输出、表达式 有时间则讲解选择语句 辅助教材为 《C语言程序设计现代方法(第2版)》 输…...

Cocos Creator2D游戏开发(10)-飞机大战(8)-计分和结束
现在游戏基本能完了, 飞机能发射子弹,打了敌机,敌机也能炸; 接下来要做计分了; 步骤: 搞出一个lable让lable显示炸了多少飞机 开搞: ①创建一个Lable标签 ② root.ts文件 添加 property(Label) player_score: Label; // 标签属性 标签绑定 ③ 代码添加 注册 然后回调 contac…...

经验分享:大数据多头借贷风险对自身的不利影响?
在现代金融体系中,大数据技术的应用使得多头借贷成为一种普遍现象。多头借贷指的是个人或企业在短时间内同时或近期内申请多笔贷款或信用产品,这种行为可能带来一系列财务和信用风险。以下是大数据多头借贷风险对个人自身可能产生的不利影响:…...

OpenCV 图像处理 轮廓检测基本原理
文章目录 基本原理关键函数和参数注意事项 示例代码示例效果代码详解findContours 函数原型findContours函数变体 基本原理 轮廓发现是图像处理中的一个重要步骤,用于检测物体的边界和形状。 图像预处理: 轮廓发现通常在灰度图像上进行。因此࿰…...
C 语言动态顺序表
test.h #ifndef _TEST_H #define _TEST_H #include <stdio.h> #include <stdlib.h> #include <string.h>typedef int data_type;// 定义顺序表结构体 typedef struct List{data_type *data; // 顺序表数据int size; // 顺序表当前长度int count; // 顺序表容…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
起重机起升机构的安全装置有哪些?
起重机起升机构的安全装置是保障吊装作业安全的关键部件,主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理: 一、超载保护装置(核心安全装置) 1. 起重量限制器 功能:实时监测起升载荷&a…...