LeetCode刷题小记 一、【数组】
LeetCode刷题小记 一、【数组】
文章目录
- LeetCode刷题小记 一、【数组】
- 写在前面
- 1. 数组
- 1.1 理论基础
- 1.2 二分查找
- 1.3 移除元素
- 1.4 有序数组的平方
- 1.5 长度最小的子数组
- 1.6 螺旋矩阵II
- Reference
写在前面
本系列笔记主要作为笔者刷题的题解,所用的语言为Python3
,若于您有助,不胜荣幸。
1. 数组
1.1 理论基础
数组[array]是一种线性的数据结构,将相同的数据类型存储在连续的内存空间当中,我们将元素在数组中的位置称为该元素的索引[index]。由于数组是连续存储的特性,我们访问其中单个元素变得十分容易,我们只需要知道其索引就能访问其中的元素,索引本质上是内存地址的偏移量。
由于数组中元素的连续存在的,因此要在数组中插入、删除元素,需要移动后续的所有元素。所以数组的各项操作的时间复杂度如下
Operation | Time Complexity |
---|---|
插入、删除 | O ( n ) \mathcal{O}(n) O(n) |
查找 | O ( 1 ) \mathcal{O}(1) O(1) |
1.2 二分查找
704二分查找
二分查找的前提是有序数组(升序或者降序),且无重复元素。
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
二分查找的第一种写法是要定义在一个左闭右闭的区间里,[left, right]
,所以终止条件就可以写为:while (left <= right)
class Solution:def search(self, nums: List[int], target: int) -> int:left: int = 0right: int = len(nums) - 1 #左闭右闭while left <= right:mid: int = (left + right) // 2if target > nums[mid]:left = mid + 1elif target < nums[mid]:right = mid - 1else:return midreturn -1
- 时间复杂度: O ( log n ) \mathcal{O}(\log n) O(logn)
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)
第二种写法是将其定义在一个左闭右开的区间,[left, right)
当中,所以终止条件必须写为:while (left < right)
class Solution:def search(self, nums: List[int], target: int) -> int:left: int = 0right: int = len(nums) #左闭右开while left < right:mid: int = left + (right - left) // 2if target > nums[mid]:left = mid + 1elif target < nums[mid]:right = midelse:return midreturn -1
35搜索插入位置
class Solution:def searchInsert(self, nums: List[int], target: int) -> int:left: int = 0right: int = len(nums)-1while left <= right:mid = left + (right - left) // 2if nums[mid] > target:right = mid - 1elif nums[mid] < target:left = mid + 1else:return midreturn left
34在排序数组中查找元素的第一个和最后一个位置
# 1、首先,在 nums 数组中二分查找 target;
# 2、如果二分查找失败,则 binarySearch 返回 -1,表明 nums 中没有 target。此时,searchRange 直接返回 {-1, -1};
# 3、如果二分查找成功,则 binarySearch 返回 nums 中值为 target 的一个下标。然后,通过左右滑动指针,来找到符合题意的区间
class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:def binarySearch(nums: List[int], target: int) -> int:left: int = 0right: int = len(nums) - 1while left <= right:mid = left + (right - left) // 2if nums[mid] > target:right = mid - 1elif nums[mid] < target:left = mid + 1else:return midreturn -1index = binarySearch(nums, target)if index == -1: return [-1, -1]left = right = indexwhile left - 1 >= 0 and nums[left - 1] == target: left -= 1while right + 1 <= len(nums) - 1 and nums[right+1] == target: right += 1return [left, right]
69x的平方根
class Solution:def mySqrt(self, x: int) -> int:if x == 0 or x == 1:return xleft: int = 1right: int = xres: int = -1while left <= right:mid = left + (right - left) // 2if mid * mid <= x: # 平方更要小于等于当前的x所以,这里用<=来限制区间res = midleft = mid + 1else:right = mid - 1return res
367有效的完全平方数
class Solution:def isPerfectSquare(self, num: int) -> bool:left: int = 1right: int = numwhile left <= right:mid = left + (right - left)//2if mid * mid > num:right = mid - 1elif mid * mid < num:left = mid + 1else:return Truereturn False
1.3 移除元素
27移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
可以使用双指针法:通过一个快指针和慢指针在一个for循环中完成两个for循环的工作。
定义快慢指针:
- 快指针:寻找新数组的元素,新数组就是不含有目标元素的数组,如果快指针指向的元素不等于
val
,那么它一定是输出数组中的元素,所以将其赋值给慢指针的位置 - 慢指针:指向更新,新数组的下标位置,如果快指针指向的元素等于
val
,说明它不是输出数组中的元素,我们直接移动快指针即可
双指针的方法,在处理数组和链表的操作当中都是非常常见的。
class Solution:def removeElement(self, nums: List[int], val: int) -> int:slowIndex: int = 0for fastIndex in range(len(nums)):if nums[fastIndex] != val:nums[slowIndex] = nums[fastIndex]slowIndex += 1return slowIndexclass Solution:def removeElement(self, nums: List[int], val: int) -> int:slowIndex: int = 0fastIndex: int = 0while fastIndex < len(nums):if nums[fastIndex] != val:nums[slowIndex] = nums[fastIndex]slowIndex += 1fastIndex += 1return slowIndex
26删除有序数组中的重复项
class Solution:def removeDuplicates(self, nums: List[int]) -> int:fastIndex: int = 1slowIndex: int = 0while fastIndex <= len(nums) - 1:if nums[slowIndex] == nums[fastIndex]:fastIndex += 1elif nums[slowIndex] != nums[fastIndex]:slowIndex += 1nums[slowIndex] = nums[fastIndex]return slowIndex + 1
283移动零
class Solution:def moveZeroes(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""slowIndex: int = 0fastIndex: int = 0while fastIndex <= len(nums) - 1:if nums[fastIndex] != 0:nums[slowIndex] = nums[fastIndex]slowIndex += 1fastIndex += 1for i in range(slowIndex, fastIndex):nums[i] = 0
1.4 有序数组的平方
977有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路,该数组已经知道为有序数组,那么数组的中间值的平方一定是最小的,最大值一定是从两侧值的平方中进行选取,所以我们可以使用左右指针开始查找。
class Solution:def sortedSquares(self, nums: List[int]) -> List[int]:leftIndex: int = 0rightIndex: int = len(nums) - 1resIndex: int = len(nums) - 1res: List[any] = [float('inf')] * len(nums)while leftIndex <= rightIndex:elem1 = nums[leftIndex] ** 2elem2 = nums[rightIndex] ** 2if elem1 >= elem2:res[resIndex] = elem1leftIndex += 1else:res[resIndex] = elem2rightIndex -= 1resIndex -= 1return res
1.5 长度最小的子数组
209长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度**。**如果不存在符合条件的子数组,返回 0
。
本题采用的思想是,滑动窗口,滑动窗口可以分为最大滑动窗口和最小滑动窗口,具体的区别在于最大滑动窗口目的在于最大化满足条件的区间长度,而最小化滑动窗口目的在于最小化满足条件的区间长度。
最小滑窗模板:给定数组 nums,定义滑窗的左右边界 i, j,求满足某个条件的滑窗的最小长度。
while j < len(nums):判断[i, j]是否满足条件while 满足条件:不断更新结果(注意在while内更新!)i += 1 (最大程度的压缩i,使得滑窗尽可能的小)j += 1
最大滑窗模板:给定数组 nums,定义滑窗的左右边界 i, j,求满足某个条件的滑窗的最大长度。
while j < len(nums):判断[i, j]是否满足条件while 不满足条件:i += 1 (最保守的压缩i,一旦满足条件了就退出压缩i的过程,使得滑窗尽可能的大)不断更新结果(注意在while外更新!)j += 1
class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:startIndex: int = 0result: any = float('inf')s: int = 0for endIndex in range(len(nums)):s += nums[endIndex]while s >= target:result = min(result, endIndex - startIndex + 1)s -= nums[startIndex]startIndex += 1return result if result != float('inf') else 0
defaultdict的用法
python中的defaultdict
是collections
库中的一种字典,与python中默认字典dict
的区别在于,我们可以指定defaultdict
当访问到不存在的key
是的返回值,比如
from collections import defaultdict
d1 = defaultdict(int) #设置d1访问不存在的key时返回0
d2 = defaultdict(list) #设置d2访问不存在的key时返回空列表[]
d2 = defaultdict(bool) #设置d3访问不存在的key时返回False
print(d1['a'])
print(d2['a'])
print(d3['a'])
返回的结果为
0
[]
False
904. 水果成篮
class Solution:def totalFruit(self, fruits: List[int]) -> int:left: int = 0right: int = 0result: int = 0classMap: dict = defaultdict(int) #访问不存在的key返回0classCnt: int = 0while right <= len(fruits) - 1:# 判断是否满足情况if classMap[fruits[right]] == 0:classCnt += 1classMap[fruits[right]] += 1# 当不满情况的时候才对left进行移动,这样能够保证滑动窗口为最大while classCnt > 2:if classMap[fruits[left]] == 1:classCnt -= 1classMap[fruits[left]] -= 1 left += 1# 结果在外面进行更新result = max(result, right - left + 1)right += 1return result
76. 最小覆盖子串
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
class Solution:def minWindow(self, s: str, t: str) -> str:left: int = 0right: int = 0strMap: dict = collections.defaultdict(int) #访问不存在的key时返回0strCnt: int = len(t)result: str = ''for char in t:strMap[char] += 1# 移动右边界while right <= len(s) - 1:# 判断当前字母是否被需要if s[right] in strMap:if strMap[s[right]] > 0:strCnt -= 1strMap[s[right]] -= 1# 压缩左边界while strCnt == 0:# 更新resultif not result or right - left + 1 < len(result):result = s[left: right + 1]# 判断当前字母是否可压缩if s[left] in strMap:if strMap[s[left]] == 0:strCnt += 1strMap[s[left]] += 1left += 1right += 1return result
1.6 螺旋矩阵II
59. 螺旋矩阵 II
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
这道题的重点在于确定循环不变量,我们要保证每次循环的写法的区间都具有一致性,所以我们在这里采用左闭右开
的方式来进行循环。
class Solution:def generateMatrix(self, n: int) -> List[List[int]]:nums: List[List[int]] = [[0] * n for _ in range(n)]startx: int = 0starty: int = 0loop: int = n // 2count: int = 1offset: int = 1for _ in range(loop):for j in range(starty, n - offset):nums[startx][j] = countcount += 1for i in range(startx, n - offset):nums[i][n - offset] = countcount += 1for j in range(n - offset, starty, -1):nums[n - offset][j] = countcount += 1for i in range(n - offset, startx, -1):nums[i][starty] = countcount += 1startx += 1starty += 1offset += 1if n % 2 == 1:nums[n // 2][n // 2] = countreturn nums
54. 螺旋矩阵
给你一个 m
行 n
列的矩阵 matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
class Solution:def spiralOrder(self, matrix: List[List[int]]) -> List[int]:m: int = len(matrix)n: int = len(matrix[0])loop: int = min(m, n) // 2print(loop)startx: int = 0starty: int = 0offset: int = 1res: List[int] = []for _ in range(loop):for j in range(starty, n - offset):res.append(matrix[startx][j])for i in range(startx, m - offset):res.append(matrix[i][n - offset])for j in range(n - offset, starty, -1):res.append(matrix[m - offset][j])for i in range(m - offset, startx, -1):res.append(matrix[i][starty])startx += 1starty += 1offset += 1if min(m, n) % 2 == 1:if m <= n:for j in range(starty, n - (offset-1)): #注意这里转完一圈之后offset实际上是被+1了,我们需要还原上一圈中的offsetres.append(matrix[startx][j])else:for i in range(startx, m - (offset-1)):res.append(matrix[i][starty])return res
Reference
[1] Hello 算法
[2] 代码随想录
相关文章:
LeetCode刷题小记 一、【数组】
LeetCode刷题小记 一、【数组】 文章目录 LeetCode刷题小记 一、【数组】写在前面1. 数组1.1 理论基础1.2 二分查找1.3 移除元素1.4 有序数组的平方1.5 长度最小的子数组1.6 螺旋矩阵II Reference 写在前面 本系列笔记主要作为笔者刷题的题解,所用的语言为Python3&…...
iOS总体框架介绍和详尽说明
iOS是由苹果公司开发的移动操作系统,为iPhone、iPad、iPod Touch等设备提供支持。iOS采用了基于Unix的核心(称为Darwin),并采用了类似于Mac OS X的图形用户界面。以下是iOS的总体框架介绍和详尽说明: UIKit框架&#…...
【C++】const与constexpr详解
1. constexpr:常量表达式 所谓常量表达式,指的就是由多个(≥1)常量组成的表达式。换句话说,如果表达式中的成员都是常量,那么该表达式就是一个常量表达式。这也意味着,常量表达式一旦确定,其值将无法修改。 实际开发中,我们经常会…...
蓝桥杯:日期统计讲解(C++)
日期统计 本题来自于:2023年十四届省赛大学B组真题 主要考察:暴力。 代码放在下面,代码中重要的细节全都写了注释,非常清晰明了: #include <bits/stdc.h> //万能头文件 using namespace std;int main() {…...
Python re.findall()中的正则表达式包含多个括号时的返回值——包含元组的列表
当re.findall()中的正则表达式包含多个括号时,返回值是一个列表,其中每个元素都是一个元组。这个元组的长度与正则表达式中括号的数量相同,元组中的每个元素都是与相应括号中的模式匹配的文本。 import re # 定义一个包含三个括号的正则表达…...

Python——列表
一、列表的特性介绍 列表和字符串⼀样也是序列类型的数据 列表内的元素直接⽤英⽂的逗号隔开,元素是可变的,所以列表是可变的数据类型,⽽字符串不是。 列表的元素可以是 Python 中的任何类型的数据对象。如:字符串、…...

无人机图像识别技术研究及应用,无人机AI算法技术理论,无人机飞行控制识别算法详解
在现代科技领域中,无人机技术是一个备受瞩目的领域。随着人们对无人机应用的需求在不断增加,无人机技术也在不断发展和改进。在众多的无人机技术中,无人机图像识别技术是其中之一。 无人机图像识别技术是利用计算机视觉技术对无人机拍摄的图像…...

清华AutoGPT:掀起AI新浪潮,与GPT4.0一较高下
引言: 随着人工智能技术的飞速发展,自然语言处理(NLP)领域迎来了一个又一个突破。最近,清华大学研发的AutoGPT成为了业界的焦点。这款AI模型以其出色的性能,展现了中国在AI领域的强大实力。 目录 引言&…...

人工智能学习与实训笔记(二):神经网络之图像分类问题
人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 目录 二、图像分类问题 2.1 尝试使用全连接神经网络 2.2 引入卷积神经网络 2.3 分类函数Softmax 2.4 交叉熵损失函数 2.5 学习率优化算法 2.6 图像预处理算法 2.6.1 随机改变亮暗、对比度和颜色等 …...

SSM框架,spring-aop的学习
代理模式 二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来…...

【设计模式】4、策略模式
文章目录 一、问题二、解决方案2.1 真实世界的类比2.2 策略模式结构2.3 适用场景2.4 实现方式2.5 优缺点2.6 与其他模式的关系 三、示例代码3.1 go3.2 rust 策略模式是一种行为设计模式,它能定义一系列算法,把每种算法分别放入独立的类中,以是…...

【C++学习手札】多态:掌握面向对象编程的动态绑定与继承机制(深入)
🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:世界上的另一个我 1:02━━━━━━️💟──────── 3:58 🔄 ◀️ ⏸ ▶️ ☰ &am…...

【机构vip教程】Android SDK手机测试环境搭建
Android SDK 的安装和环境变量的配置 前置条件:需已安装 jdk1.8及 以上版本 1、下载Android SDK,解压后即可(全英文路径);下载地址:http://tools.android-studio.org/index.php/sdk 2、新建一个环境变量&…...

2024.2.18
使用fgets统计给定文件的行数 #include<stdio.h> #include<string.h> int main(int argc, const char *argv[]) {FILE *fpNULL;if((fpfopen("./test.txt","w"))NULL){perror("open err");return -1;}fputc(h,fp);fputc(\n,fp);fput…...
Haproxy实验
环境: servera(Haproxy):192.168.233.132 serverb(web1):192.168.233.144 serverc(web2):192.168.233.140 serverd(客户端):192.168.233.141 servera(Haproxy): yum install haproxy -y vim /etc/haproxy/haproxy.cfg(配置文件) # 设置日志&#…...

CSRNET图像修复,DNN
CSRNET图像修复 CSRNET图像修复,只需要OPENCV的DNN...

004 - Hugo, 分类
004 - Hugo, 分类content文件夹 004 - Hugo, 分类 content文件夹 ├─.obsidian ├─categories │ ├─Python │ └─Test ├─page │ ├─about │ ├─archives │ ├─links │ └─search └─post├─chinese-test├─emoji-support├─Git教程├─Hugo分类├─…...
Vue3之ElementPlus中Table选中数据的获取与清空方法
Vue3之ElementPlus中Table选中数据的获取与清空方法 文章目录 Vue3之ElementPlus中Table选中数据的获取与清空方法1. 点击按钮获取与清空选中表格的数据1. 用到ElementPlus中Table的两个方法2. 业务场景3. 操作案例 1. 点击按钮获取与清空选中表格的数据 1. 用到ElementPlus中…...
Leetcode 516.最长回文子序列
题意理解: 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 回文理解为元素对称的字串,这里…...

cool Node后端 中实现中间件的书写
1.需求 在node后端中,想实现一个专门鉴权的文件配置,可以这样来解释 就是 有些接口需要token调用接口,有些接口不需要使用token 调用 这期来详细说明一下 什么是中间件中间件顾名思义是指在请求和响应中间,进行请求数据的拦截处理…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...