LC打怪录 数组array

 数组(Array)

definition: 一种线性表数据结构。它使用一组连续的内存空间,来存储一组具有相同类型的数据。

如上图所示,假设数据元素的个数为 nnn,则数组中的每一个数据元素都有自己的下标索引,下标索引从 000 开始,到 n−1n - 1n−1 结束。数组中的每一个「下标索引」,都有一个与之相对应的「数据元素」。

从上图还可以看出,数组在计算机中的表示,就是一片连续的存储单元。数组中的每一个数据元素都占有一定的存储单元,每个存储单元都有自己的内存地址,并且元素之间是紧密排列的。

  1. 线性表:线性表就是所有数据元素排成像一条线一样的结构,线性表上的数据元素都是相同类型,且每个数据元素最多只有前、后两个方向。数组就是一种线性表结构,此外,栈、队列、链表都是线性表结构。
  2. 连续的内存空间:线性表有两种存储结构:「顺序存储结构」和「链式存储结构」。其中,「顺序存储结构」是指占用的内存空间是连续的,相邻数据元素之间,物理内存上的存储位置也相邻。数组也是采用了顺序存储结构,并且存储的数据都是相同类型的。

原生 Python 中其实没有数组的概念,而是使用了类似 Java 中的 ArrayList 容器类数据结构,叫做列表。通常我们把列表来作为 Python 中的数组使用。Python 中列表存储的数据类型可以不一致,数组长度也可以不一致。例如:

arr = ['python', 'java', ['asp', 'php'], 'c']

数组的优点与局限性¶

数组存储在连续的内存空间内,且元素类型相同。这种做法包含丰富的先验信息,系统可以利用这些信息来优化数据结构的操作效率。

  • 空间效率高:数组为数据分配了连续的内存块,无须额外的结构开销。
  • 支持随机访问:数组允许在 �(1) 时间内访问任何元素。
  • 缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓存来提升后续操作的执行速度。

连续空间存储是一把双刃剑,其存在以下局限性。

  • 插入与删除效率低:当数组中元素较多时,插入与删除操作需要移动大量的元素。
  • 长度不可变:数组在初始化后长度就固定了,扩容数组需要将所有数据复制到新数组,开销很大。
  • 空间浪费:如果数组分配的大小超过实际所需,那么多余的空间就被浪费了

题目

438. 找到字符串中所有字母异位词

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

189. 轮转数组 rotate array

方法1: 创建新的数组

创建新的数组,使用额外的储存空间

python切片语法
列表切片语法:
  • 基本形式:list[start:stop:step]
    • start是切片开始的索引(包含该索引指向的元素),默认值为0。
    • stop是切片结束的索引(不包含该索引指向的元素),默认值为列表长度。
    • step是切片的步长,表示取元素的间隔,默认值为1。
使用[:]进行列表复制:
  • 当你省略startstop索引时(即[:]),切片操作会选取整个列表。
  • 这种方式实现的是列表的浅拷贝,意味着列表本身被复制了,但是列表中的元素并没有被复制。如果列表中的元素是不可变类型(如整数、字符串等),这通常不会引起问题。但如果列表中包含可变对象(如其他列表),则原始列表和复制的列表中的可变元素将指向相同的对象。
  • example: 
    original_list = [1, 2, 3, 4]
    copied_list = original_list[:]  # 创建 original_list 的一个浅拷贝# 修改 copied_list 不会影响 original_list
    copied_list.append(5)
    print(original_list)  # 输出: [1, 2, 3, 4]
    print(copied_list)    # 输出: [1, 2, 3, 4, 5]
    
1. 暴力法3种写法
insert and pop
class Solution(object):def rotate(self, nums, k):""":type nums: List[int]:type k: int:rtype: None Do not return anything, modify nums in-place instead."""res = nums[:] #创建列表副本:res = nums[:] 创建了nums的一个副本,名为res。这样做是为了在不改变原始列表的情况下,先在副本上进行修改。n=len(nums)for i in range(n):pos =(i+k)%nres[pos]=nums[i]for i in range(n):nums[i]=res[i]
  • 计算新位置并填充到副本

    • n = len(nums) 获取列表nums的长度,存储在变量n中。
    • 接着使用一个循环for i in range(n):来遍历nums中的每个元素。
      • 对于每个元素的索引i,计算它旋转k步后的新位置pos,这通过(i+k)%n得到。这里使用取模操作符%是为了处理k大于列表长度的情况,确保计算出的位置索引不会超出列表范围。
      • 然后将原始列表nums中索引为i的元素赋值给副本res中计算出的新位置pos
  • 将修改后的副本复制回原列表

    • 使用另一个循环for i in range(n):来遍历修改后的副本res
    • nums[i] = res[i]将副本res中的每个元素复制回原始列表nums的对应位置
  • 时间复杂度: O(n) + O(n) + O(n) = O(n)
  • 空间复杂度:O(n)

综合来看,这个旋转数组的方法是时间效率较高(线性时间复杂度),但在空间上并不是最优的,因为它需要额外的空间来存储整个数组的副本。在一些对空间敏感的场景下,可能需要考虑其他更节省空间的旋转方法。

 2. 切片并拼接
class Solution:def rotate(self, nums: List[int], k: int) -> None:"""Do not return anything, modify nums in-place instead."""n = len(nums) #Gets the length of the nums list and stores it in n.k = k % n #Updates k to k % n to handle cases where k is greater than n. #This step ensures that the rotation count is within the range of the list's length.nums[:] = nums[n - k:] + nums[:n - k]

 Rotating the List: The list is rotated by slicing and rearranging its elements:

  • nums[:] = nums[n - k:] + nums[:n - k]: This line is the key to rotating the list. It works as follows:
    • nums[n - k:]: Takes a slice of the last k elements from the list.
    • nums[:n - k]: Takes a slice of the first n - k elements from the list.
    • nums[n - k:] + nums[:n - k]: Concatenates the last k elements with the first n - k elements, effectively rotating the list to the right by k steps.
    • nums[:] =: Assigns the newly arranged list back to nums. Using nums[:] instead of nums for assignment modifies the list in place, meaning the original list passed to the function is changed outside the function as well.

综合来看,这个解法在时间复杂度上与前一个方法相同(都是O(n)),但在空间复杂度上更优(O(1) vs. O(n)),因为它避免了创建整个数组副本的需要。这使得它在空间使用上更为高效,特别是对于大数据量的情况。

2. reverse 

class Solution:def rotate(self, nums: List[int], k: int) -> None:"""Do not return anything, modify nums in-place instead."""def reverse(l,r):while (l<r):nums[l],nums[r]= nums[r],nums[l]l += 1r -= 1n = len(nums)k = k % n #计算实际的旋转步数reverse(0, n-1) #翻转整个列表reverse(0, k-1) #翻转前k个元素reverse(k,n-1) #翻转剩余的元素
辅助函数reverse
  • reverse(l, r): 这个内部定义的函数用于翻转nums列表中索引从lr(包含lr)的元素。它通过一个while循环交换两端的元素,直到中间相遇
主方法rotate
  1. 计算实际的旋转步数:因为列表的长度可能小于旋转步数k,所以首先通过k = k % n计算实际需要旋转的步数(n是列表的长度)。这样做的目的是处理k大于列表长度的情况,确保旋转步数是有效的。

  2. 翻转整个列表:通过调用reverse(0, n-1)翻转整个列表。这个步骤是将列表看作是一个环,通过翻转来初始化旋转操作。

  3. 翻转前k个元素:然后通过reverse(0, k-1)仅翻转列表中前k个元素。由于整个列表在第一步中已经翻转过了,这一步实际上是将最初的后k个元素移动到了列表的前面。

  4. 翻转剩余的元素:最后,通过reverse(k, n-1)翻转索引从kn-1的元素,即列表中剩余的部分。这一步将这部分元素恢复到正确的顺序。

示例

假设nums = [1,2,3,4,5,6,7]k = 3,那么旋转的步骤如下:

  1. 原始列表:[1,2,3,4,5,6,7]
  2. 翻转整个列表:[7,6,5,4,3,2,1]
  3. 翻转前k个元素:[5,6,7,4,3,2,1]
  4. 翻转剩余的元素:[5,6,7,1,2,3,4]
最终结果是[5,6,7,1,2,3,4],即将原始列表向右旋转了3步。

66. 加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

class Solution(object):def plusOne(self, digits):""":type digits: List[int]:rtype: List[int]"""s = '' #定义一个空字符串s,用于临时存储digits数组表示的数字。l = [] #定义一个空列表l,用于存储最终结果。for i in range(len(digits)):s += str(digits[i])s = str(int(s)+1)for i in s:l.append(int(i))return l

方法步骤详解

将数字数组转换为字符串

  • 通过一个循环for i in range(len(digits)):遍历digits数组。
  • s += str(digits[i]):将每个数字转换为字符串并附加到s上。这一步骤将数字数组如[1, 2, 3]转换为字符串"123"

字符串数字加一

  • s = str(int(s)+1):将字符串s转换为整数并加一,然后再次转换为字符串。这一步处理了整数加一的操作。例如,如果s"123",加一后会变成"124"

将结果字符串转换回数字数组

  • 再次使用循环for i in s:遍历字符串中的每个字符。
  • l.append(int(i)):将每个字符转换回整数并添加到列表l中。例如,如果s"124",则l将变为[1, 2, 4]

返回结果

  • return l返回列表l作为最终结果。

示例

假设输入digits = [1, 2, 3],方法的执行过程如下:

  1. digits转换为字符串s = "123"
  2. 将字符串表示的数字加一得到s = "124"
  3. 将字符串s转换回数组l = [1, 2, 4]
  4. 返回结果[1, 2, 4]

724. 寻找数组的中心下标

示例 1:

输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
中心下标是 3 。
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
class Solution:def pivotIndex(self, nums: List[int]) -> int:sum_left, sum_right = 0, sum(nums)for i in range(len(nums)):sum_right -= nums[i]# 若左侧元素和等于右侧元素和,返回中心下标 iif sum_left == sum_right:return isum_left += nums[i]return -1

方法步骤详解

  1. 初始化变量

    • sum_left, sum_right = 0, sum(nums)sum_left用于存储当前索引左侧元素的和(初始值为0),sum_right用于存储整个数组的和,表示初始时右侧元素的总和。
  2. 遍历数组

    • 使用for i in range(len(nums)):遍历数组中的每个元素。变量i代表当前考虑的中心索引。
  3. 更新右侧和并检查条件

    • sum_right -= nums[i]:在每次循环开始时,从右侧元素和中减去当前元素,因为此元素将被考虑为中心索引的左侧部分。
    • if sum_left == sum_right::检查当前的左侧和是否等于右侧和。如果相等,说明找到了中心索引,直接返回该索引i
  4. 更新左侧和

    • sum_left += nums[i]:将当前元素加到左侧和中,因为在下一次迭代中,当前元素将属于左侧部分。
  5. 遍历结束后

    • 如果遍历了整个数组都没有找到符合条件的中心索引,则返回-1。

示例

假设输入nums = [1, 7, 3, 6, 5, 6],方法的执行过程如下:

  1. 初始sum_left = 0sum_right = 28(数组元素之和)。
  2. 遍历开始,i = 0sum_right更新为27,左侧和不等于右侧和,继续遍历。
  3. i = 3时,sum_left = 11(1+7+3),sum_right也为11(5+6),左侧和等于右侧和,因此返回中心索引3

这种方法的优点是只需要一次遍历就可以找到中心索引(如果存在的话),时间复杂度为O(n),空间复杂度为O(1)(只使用了有限的额外空间)。这种方法既高效又简洁。

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

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

相关文章

基于机器学习的工业用电量预测完整代码数据

视频讲解: 毕业设计:算法+系统基于机器学习的工业用电量预测完整代码数据_哔哩哔哩_bilibili 界面展示: 结果分析与展示: 代码: from sklearn import preprocessing import random from sklearn.model_selection import train_test_split from sklearn.preprocessing…

超网、IP 聚合、IP 汇总分别是什么?三者有啥区别和联系?

一、超网 超网&#xff08;Supernet&#xff09;是一种网络地址聚合技术&#xff0c;它可以将多个连续的网络地址合并成一个更大的网络地址&#xff0c;从而减少路由表的数量和大小。超网技术可以将多个相邻的网络地址归并成一个更大的网络地址&#xff0c;这个更大的网络地址…

从零开始:神经网络(1)——神经元和梯度下降

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 一. 神经网络 1. 神经网络的发展 先了解一下神经网络发展的历程。从单层神经网络&#xff08;感知器&#xff09;开…

excel统计分析——嵌套设计

参考资料&#xff1a;生物统计学&#xff0c;巢式嵌套设计的方差分析 嵌套设计&#xff08;nested design&#xff09;也称为系统分组设计或巢式设计&#xff0c;是把试验空间逐级向低层次划分的试验设计方法。与裂区设计相似&#xff0c;先按一级因素设计试验&#xff0c;然后…

高度塌陷问题及解决

什么情况下产生 (when 父盒子没有定义高度&#xff0c;但是子元素有高度&#xff0c;希望用子盒子撑起父盒子的高度&#xff0c;但是子盒子添加了浮动属性之后&#xff0c;父盒子高度为0 <template><div class"father"><div class"son"&…

R统计学2 - 数据分析入门问题21-40

往期R统计学文章&#xff1a; R统计学1 - 基础操作入门问题1-20 21. 如何对矩阵按行 (列) 作计算&#xff1f; 使用函数 apply() vec 1:20 # 转换为矩阵 mat matrix (vec , ncol4) # [,1] [,2] [,3] [,4] # [1,] 1 6 11 16 # [2,] 2 7 12 17 # [3,] …

了解华为(PVID VLAN)与思科的(Native VLAN)本征VLAN的区别并学习思科网络中二层交换机的三层结构局域网VLAN配置

一、什么是二层交换机&#xff1f; 二层交换机&#xff08;Layer 2 Switch&#xff09;是一种网络设备&#xff0c;主要工作在OSI模型的数据链路层&#xff08;第二层&#xff09;&#xff0c;用于在局域网内部进行数据包的交换和转发。二层交换机通过学习MAC地址表&#xff0…

codeforcesABC

A A. Marathon time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output DeepL 翻译  A.马拉松 每次测试的时间限制&#xff1a;1 秒 每次测试的内存限制&#xff1a;256 兆字节 输入&#xff1a…

简单认识Linux

今天带大家简单认识一下Linux&#xff0c;它和我们日常用的Windows有什么不同呢&#xff1f; Linux介绍 Linux内核&发行版 Linux内核版本 内核(kernel)是系统的心脏&#xff0c;是运行程序和管理像磁盘和打印机等硬件设备的核心程序&#xff0c;它提供了一个在裸设备与…

Nginx配置文件的整体结构

一、Nginx配置文件的整体结构 从图中可以看出主要包含以下几大部分内容&#xff1a; 1. 全局块 该部分配置主要影响Nginx全局&#xff0c;通常包括下面几个部分&#xff1a; 配置运行Nginx服务器用户&#xff08;组&#xff09; worker process数 Nginx进程PID存放路径 错误…

Normalizer(归一化)和MinMaxScaler(最小-最大标准化)的区别详解

1.Normalizer&#xff08;归一化&#xff09;&#xff08;更加推荐使用&#xff09; 优点&#xff1a;将每个样本向量的欧几里德长度缩放为1&#xff0c;适用于计算样本之间的相似性。 缺点&#xff1a;只对每个样本的特征进行缩放&#xff0c;不保留原始数据的分布形状。 公式…

【ubuntu】安装 Anaconda3

目录 一、Anaconda 说明 二、操作记录 2.1 下载安装包 2.1.1 官网下载 2.1.2 镜像下载 2.2 安装 2.2.1 安装必要的依赖包 2.2.2 正式安装 2.2.3 检测是否安装成功 方法一 方法二 方法三 2.3 其他 三、参考资料 3.1 安装资料 3.2 验证是否成功的资料 四、其他 …

STM32---通用定时器(二)相关实验

写在前面&#xff1a;前面我们学习了基本定时器、通用定时器的相关理论部分&#xff0c;了解到通用定时器的结构框图&#xff0c;总共包含六大模块&#xff1a;时钟源、控制器、时基单元、输入捕获、公共部分以及输出捕获。对相关模块的使用也做详细的讲解。本节我们主要是对上…

【HarmonyOS】ArkTS-枚举类型

枚举类型 枚举类型是一种特殊的数据类型&#xff0c;约定变量只能在一组数据范围内选择值 定义枚举类型 定义枚举类型&#xff08;常量列表&#xff09; enum 枚举名 { 常量1 值, 常量2 值,......}enum ThemeColor {Red #ff0f29,Orange #ff7100,Green #30b30e}使用枚举…

读算法的陷阱:超级平台、算法垄断与场景欺骗笔记05_共谋(中)

1. 默许共谋 1.1. 又称寡头价格协调&#xff08;Oligopolistic Price Coordination&#xff09;或有意识的平行行为&#xff08;Conscious Parallelism&#xff09; 1.1.1. 在条件允许的情况下&#xff0c;它会发生在市场集中度较高的行业当中 1.1.…

你还可以通过“nrm”工具,来自由管理“npm”的镜像

你还可以通过“nrm”工具&#xff0c;来自由管理“npm”的镜像 nrm&#xff08;npm registry manager&#xff09;是npm的镜像管理工具&#xff0c;有时候国外的资源太慢&#xff0c;使用这个就可以快速地在npm源间切换。 1.安装nrm 在命令行执行命令&#xff0c;npm install…

如何免费获得一个市全年的气象数据?降雨量气温湿度太阳辐射等等数据

气象数据一直是一个价值较高的数据&#xff0c;它被广泛用于各个领域的研究当中。气象数据包括有气温、气压、相对湿度、降水、蒸发、风向风速、日照等多种指标&#xff0c;但是包含了这些全部指标的气象数据却较难获取&#xff0c;即使获取到了也不能随意分享。 想要大规模爬取…

抽象的java发送邮箱2.0版本

优化了更多细节 SpringBoot3&#xff1a;前置框架 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><dependency><groupId>org.springframewo…

【工具】Git的24种常用命令

相关链接 传送门&#xff1a;>>>【工具】Git的介绍与安装<< 1.Git配置邮箱和用户 第一次使用Git软件&#xff0c;需要告诉Git软件你的名称和邮箱&#xff0c;否则无法将文件纳入到版本库中进行版本管理。 原因&#xff1a;多人协作时&#xff0c;不同的用户可…

Python匿名函数有知道的吗?

1.函数 按照函数是否有名字分为有名字的函数和匿名函数 匿名函数&#xff1a;定义函数时&#xff0c;不再使用def关键字声明函数&#xff0c;而是使用lambda表达式 匿名函数在需要执行简单的操作时非常有用&#xff0c;可以减少代码冗余 2.有名字的函数 def fn(n):return …