7、线性数据结构-切片

切片slice

  • 容器容量可变,所以长度不能定死
  • 长度可变,元素个数可变
  • 底层必须依赖数组,可以理解它依赖于顺序表,表现也像个可变容量和长度顺序表
  • 引用类型,和值类型有区别

定义切片

var s1 []int //长度、容量为0的切片,零值
var s2 = []int{}	//长度、容量为0的切片,字面量定义
var s3 = []int{1,3,5}	//字面量定义,长度、容量都是3
var s4 = make([]int,0)	//长度、容量都为0的切片,make([]T,length)
var s5 = make([]int,3,5) //长度为3,容量为5,底层数组长度为5,元素长度为3,所以显示[0,0,0]

使用切片要关注容量cap和长度len两个属性

内存模型

切片本质是对底层数组一个连续片段的引用。此片段可以是整个底层数组,也可以是由起始和终止索引标识的一些项的子集。

因为下面是底层数组,所以数组的容量是不可以改变的。元素内容能变的。

理解:切片保存的就是标头值,该值包括,指向的实际存储的地址,实际长度和容量的长度

由上图可知,pointer的实际地址和底层数组的地址是不同的

// https://github.com/golang/go/blob/master/src/runtime/slice.go
// slice header 或 descriptor
type slice struct {array unsafe.Pointer    指向底层数组的指针len int				切片访问的元素的个数(即长度)cap int				切片允许增长到的元素个数(即容量)
}
注意上面三个结构体的属性都是小写,所以包外不可见。len函数取就是len属性,cap函数取cap属性。
func main() {var s1 = make([]int, 3, 5)fmt.Printf("s1 %p %p %d", &s1, &s1[0], s1)}
s1 0xc000008078 0xc00000e450 [0 0 0]分析结果:&s1指的是标头值的地址  表示切片的地址,header这个结构体的地址&s1[0] 指的是实际存储的起始元素的地址, 第一个元素的地址,由于第一个元素存在底层数组中,数组的第一个元素地址就是数组的地址指针可以通过取底层数组的第一个元素的地址,即切片第一个元素的地址

追加

append:在切片的尾部追加元素,长度加1。
增加元素后,有可能超过当前容量,导致切片扩容。

切片扩容就是底层数组会出现起始一段地址

长度和容量

func main() {s1 := []int{100}fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s1 = make([]int, 2, 5)fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)
}s1 0xc000008078 0xc00001a098,1,1,[100]
s1 0xc000008078 0xc0000103f0,2,5,[0 0]结论:s1被重新复制了,但是S1的地址没有变化,底层数组的地址发生了变化
追加
func main() {s1 := make([]int, 2, 5)   //定义了一个长度为2,容量为5的切片,fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s1 = append(s1, 200)	// append返回新的header信息,覆盖fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)
}s1 0xc000008078 0xc0000103f0,2,5,[0 0]
s1 0xc000008078 0xc0000103f0,3,5,[0 0 200]
结论: s1的地址和底层数组的地址都没有发生变化,这是因为没有超过容量,底层共用同一个数组,但是,对底层数组使用的片段不一样。
func main() {s1 := make([]int, 2, 5)fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s1 = append(s1, 200)fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s2 := append(s1, 1, 2)	// append返回新的header信息,使用新的变量存储fmt.Printf("s2 %p %p,%d,%d,%v\n", &s2, &s2[0], len(s2), cap(s2), s2)
}
s1 0xc000008078 0xc0000103f0,2,5,[0 0]
s1 0xc000008078 0xc0000103f0,3,5,[0 0 200]
s2 0xc0000080c0 0xc0000103f0,5,5,[0 0 200 1 2]
结论:我们发现有新的header值,因为切片的重新赋值,所以s2有新的地址,但是s2指向的底层数组还是一样的,因为容量还没有超出。
func main() {s1 := make([]int, 2, 5)fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s2 := append(s1, 1, 2)fmt.Printf("s2 %p %p,%d,%d,%v\n", &s2, &s2[0], len(s2), cap(s2), s2)s3 := append(s1, -1)fmt.Printf("s3 %p %p, %d,%d,%v\n", &s3, &s3[0], len(s3), cap(s3),s3)
}
s1 0xc000008078 0xc0000103f0,2,5,[0 0]
s2 0xc0000080a8 0xc0000103f0,4,5,[0 0 1 2]
s3 0xc0000080d8 0xc0000103f0, 3,5,[0 0 -1]结论:目前三个切片底层用同一个数组,只不过长度不一样
func main() {s1 := make([]int, 2, 5)fmt.Printf("s1 %p %p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s2 := append(s1, 1, 2)fmt.Printf("s2 %p %p,%d,%d,%v\n", &s2, &s2[0], len(s2), cap(s2), s2)s3 := append(s1, -1)fmt.Printf("s3 %p, %p, %d,%d,%v\n", &s3, &s3[0], len(s3), cap(s3), s3)s4 := append(s3, 3, 4, 5, 6)fmt.Printf("s4 %p, %p, %d,%d,%v\n", &s4, &s4[0], len(s4), cap(s4), s4)}
s1 0xc000008078 0xc0000103f0,2,5,[0 0]
s2 0xc0000080a8 0xc0000103f0,4,5,[0 0 1 2]
s3 0xc0000080d8, 0xc0000103f0, 3,5,[0 0 -1]
s4 0xc000008108, 0xc0000142d0, 7,10,[0 0 -1 3 4 5 6]结论:底层数组变了,容量也增加了 ,底层数组的起始地址也发生了变化,相当于重新在内存中开辟了一块地址,并且容量变成了之前的2

结论:

  • append一定返回一个新的切片,但本质上来说返回的是新的Header
  • append可以增加若干元素
    • 如果增加元素时,当前长度 + 新增个数 <= cap则不扩容
      • 原切片使用原来的底层数组,返回的新切片也使用这个底层数组
      • 返回的新切片有新的长度
      • 原切片长度不变
    • 如果增加元素时,当前长度 + 新增个数 > cap则需要扩容
      • 生成新的底层数组,新生成的切片使用该新数组,将旧元素复制到新数组,其后追加新元素
      • 原切片底层数组、长度、容量不变

扩容策略

​ (老版本)实际上,当扩容后的cap<1024时,扩容翻倍,容量变成之前的2倍;当cap>=1024时,变成
之前的1.25倍。
​ (新版本1.18+)阈值变成了256,当扩容后的cap<256时,扩容翻倍,容量变成之前的2倍;当
cap>=256时, newcap += (newcap + 3*threshold) / 4 计算后就是 newcap = newcap +newcap/4 + 192 ,即1.25倍后再加192。
​ 扩容是创建新的底层数组,把原内存数据拷贝到新内存空间,然后在新内存空间上执行元素追加操作。
​ 切片频繁扩容成本非常高,所以尽量早估算出使用的大小,一次性给够,建议使用make。常用make([]int, 0, 100) 。

子切片

选取当前切片的一段等到一个新的切片,共用底层数据(因为不扩容),但是header中的三个属性会变,切片可以通过指定索引区间获得一个子切片,格式为slice[start:end],规则就是前包后不包。

package mainimport "fmt"func main() {s1 := []int{10, 30, 50, 70, 90}for i := 0; i < len(s1); i++ {fmt.Printf("%d : addr = %p\n", i, &s1[i])}
}
0 : addr = 0xc00013a060
1 : addr = 0xc00013a068
2 : addr = 0xc00013a070
3 : addr = 0xc00013a078
4 : addr = 0xc00013a080
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s2 := s1	//共用一个底层数组fmt.Printf("s2 %p,%p,%d,%d,%v\n", &s2, &s2[0], len(s2), cap(s2), s2)}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s2 0xc0000080a8,0xc0000103f0,5,5,[10 30 50 70 90]结论:s2复制s1的标头值,但是s2也被重新赋值了
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s2 := s1fmt.Printf("s2 %p,%p,%d,%d,%v\n", &s2, &s2[0], len(s2), cap(s2), s2)s3 := s1[:]fmt.Printf("s3 %p,%p,%d,%d,%v\n", &s3, &s3[0], len(s3), cap(s3), s3)
}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s2 0xc0000080a8,0xc0000103f0,5,5,[10 30 50 70 90]
s3 0xc0000080d8,0xc0000103f0,5,5,[10 30 50 70 90]
结论:s3 := s1[:] 这个代表的就是从头到尾的元素都要,和s1共用一个底层数组
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s4 := s1[1:]fmt.Printf("s4 %p,%p,%d,%d,%v\n", &s4, &s4[0], len(s4), cap(s4), s4)
}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s4 0xc0000080a8,0xc0000103f8,4,4,[30 50 70 90]结论: s4 := s1[1:] 掐头,从1开始容量长度都发生变化 首地址偏移了一位,因此长度len=end-start=4 cap=cap-start=4
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s5 := s1[1:4]fmt.Printf("s5 %p,%p,%d,%d,%v\n", &s5, &s5[0], len(s5), cap(s5), s5)
}
s1 0xc000092060,0xc0000be060,5,5,[10 30 50 70 90]
s5 0xc000092090,0xc0000be068,3,4,[30 50 70]
结论:s5 := s1[1:4]  掐头去尾,但是前包后不包 就是1的位置的元素包含在里,4的位置的元素不在
len=end-start=3  cap=start的这个位置到容器的最大位置=4

func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s6 := s1[:4]fmt.Printf("s6 %p,%p,%d,%d,%v\n", &s6, &s6[0], len(s6), cap(s6), s6)
}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s6 0xc0000080a8,0xc0000103f0,4,5,[10 30 50 70]
结论:s6 := s1[:4]  去尾,后不包 len=4-0=4 容量=第一个位置到最大的容量值=5 cap=cap-start 首地址还不变
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s7 := s1[1:1]fmt.Printf("s7 %p,%d,%d,%v\n", &s7, len(s7), cap(s7), s7)
}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s7 0xc0000080a8,0,4,[]结论:首地址偏移1个元素,长度为0cap=cap-start 容量为4,共用底层数组  由于长度为0,所以不能s7[0]报错

为s7增加一个元素,s1、s7分别是什么?

func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s7 := s1[1:1]s7 = append(s7, 100)fmt.Printf("s7 %p,%p,%d,%d,%v\n", &s7, &s7[0], len(s7), cap(s7), s7)fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s7 0xc0000080a8,0xc0000103f8,1,4,[100]
s1 0xc000008078,0xc0000103f0,5,5,[10 100 50 70 90]
结论:s7操作的也是在底层数组中,所以s7在1新增了100 底层数组s1的1位置30修改为了100 
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s8 := s1[4:4]fmt.Printf("s8 %p,%d,%d,%v\n", &s8, len(s8), cap(s8), s8)}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s8 0xc0000080a8,0,1,[]
// 首地址偏移4个元素,长度为0,容量为1,因为最后一个元素没在切片中,共用底层数组
func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s9 := s1[5:5]fmt.Printf("s9 %p,%d,%d,%v\n", &s9, len(s9), cap(s9), s9)
}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s9 0xc0000080a8,0,0,[]增加元素会怎么样?s1、s9分别是什么?func main() {s1 := []int{10, 30, 50, 70, 90}fmt.Printf("s1 %p,%p,%d,%d,%v\n", &s1, &s1[0], len(s1), cap(s1), s1)s9 := s1[5:5]fmt.Printf("s9 %p,%d,%d,%v\n", &s9, len(s9), cap(s9), s9)s9 = append(s9, 100)fmt.Printf("s9 %p,%p,%d,%d,%v\n", &s9, &s9[0], len(s9), cap(s9), s9)
}
s1 0xc000008078,0xc0000103f0,5,5,[10 30 50 70 90]
s9 0xc0000080a8,0,0,[]
s9 0xc0000080a8,0xc00001a0e8,1,1,[100]

切片总结:

  • 使用slice[start:end]表示切片,切片长度为end-start,前包后不包
  • start缺省,表示从索引0开始
  • end缺省,表示取到末尾,包含最后一个元素,特别注意这个缺省值是len(slice)即切片长度,不是容量
    • a1[5:]相当于a1[5:len(a1)]
  • start和end都缺省,表示从头到尾
  • start和end同时给出,要求end >= start
    • start、end最大都不可以超过容量值
    • 假设当前容量是8,长度为5,有以下情况
      • a1[:],可以,共用底层数组,相当于对标头值的拷贝,也就是指针、长度、容量都一样
      • a1[:8],可以,end最多写成8(因为后不包),a1[:9]不可以。该切片长度、容量都为8,
        这8个元素都是原序列的,一旦append就扩容
      • a1[8:],不可以,end缺省为当前长度5,等价于a1[8:5]
      • a1[8:8],可以,但这个切片容量和长度都为0了。注意和a1[:8]的区别
      • a1[7:7],可以,但这个切片长度为0,容量为1
      • a1[0:0],可以,但这个切片长度为0,容量为8
      • a1[1:5],可以,这个切片长度为4,容量为7,相当于跳过了原序列第一个元素
  • 切片刚产生时,和原序列(数组、切片)开始共用同一个底层数组,但是每一个切片都自己独立保存着指针、cap和len
  • 一旦一个切片扩容,就和原来共用一个底层数组的序列分道扬镳,从此陌路

后不包),a1[:9]不可以。该切片长度、容量都为8,
这8个元素都是原序列的,一旦append就扩容
- a1[8:],不可以,end缺省为当前长度5,等价于a1[8:5]
- a1[8:8],可以,但这个切片容量和长度都为0了。注意和a1[:8]的区别
- a1[7:7],可以,但这个切片长度为0,容量为1
- a1[0:0],可以,但这个切片长度为0,容量为8
- a1[1:5],可以,这个切片长度为4,容量为7,相当于跳过了原序列第一个元素

  • 切片刚产生时,和原序列(数组、切片)开始共用同一个底层数组,但是每一个切片都自己独立保存着指针、cap和len
  • 一旦一个切片扩容,就和原来共用一个底层数组的序列分道扬镳,从此陌路

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

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

相关文章

11月14日,每日信息差

今天是2023年11月14日&#xff0c;以下是为您准备的11条信息差 第一、中国航司首开“上海-开罗”往返直飞航线&#xff0c;12月11日首航 第二、中核集团&#xff1a;我国首次获得丰度99%以上的镱176同位素 第三、微软与谷歌将不会挑战欧盟的数据迁移法规&#xff0c;该法律将…

ProEasy机器人:运动+通讯相关说明

----------------机械手运动------- --常用指令&#xff1a;MovP弧线运动、MovL直线运动 MovP(1) --弧线轨迹运动到一号点 MovP(2) --弧线轨迹运动到二号点 MovL(1) --直线轨迹运动到一号点 MovL(2) --直线轨迹运…

LeetCode——链表(Java)

链表 简介[简单] 203. 移除链表元素[中等] 707. 设计链表[简单] 206. 反转链表[简单] 24. 两两交换链表中的节点[简单] 19. 删除链表的倒数第 N 个结点 简介 记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录。会附上一些个人的思路&#xff0c;如果有错误&#…

VB生成UTF-8的URL编码

最近在研发股票软件&#xff0c;涉及到URL字符串的处理。贴出以下代码。 Function GBtoUTF8(szInput) Dim wch, uch, szRet Dim x Dim nAsc, nAsc2, nAsc3 如果输入参数为空&#xff0c;则退出函数 If szInput "" Then GBtoUTF8 szInput Exit Function End If 开始…

前、后端程序员开发常用api接口

顺丰速运开放平台&#xff1a;可以查询顺丰速运的快递信息。京东物流开放平台&#xff1a;可以查询京东物流的快递信息。全国快递物流查询&#xff1a;1.提供包括申通、顺丰、圆通、韵达、中通、汇通等600快递公司在内的快递物流单号查询。2.与官网实时同步更新。3.自动识别快递…

【C++】join ()和detach ()函数详解和示例

简单的来说&#xff0c;join ()方法建立的线程具有阻碍作用&#xff0c;该线程不结束&#xff0c;另一些函数就无法运行。detach ()方法建立的线程&#xff0c;可以和另一些函数同时进行。下面以示例进行详细说明&#xff0c;以帮助大家理解和使用。 目录 join ()detach () jo…

PHP使用文件缓存实现html静态化

<?php // 动态生成的内容 $content "<html><body><h1>time:".date("Y-m-d H:i:s")."</h1></body></html>"; // 静态文件保存路径和文件名 $staticFilePath "file.html"; if(file_exists($s…

Ladybug 全景相机, 360°球形成像,带来全方位的视觉体验

360无死角全景照片总能给人带来强烈的视觉震撼&#xff0c;有着大片的既视感。那怎么才能拍出360球形照片呢&#xff1f;它的拍摄原理是通过图片某个点位为中心将图片其他部位螺旋式、旋转式处理&#xff0c;从而达到沉浸式体验的效果。俗话说“工欲善其事&#xff0c;必先利其…

java实现计数排序

图解 计数排序是一种线性时间复杂度的排序算法&#xff0c;它不基于比较排序&#xff0c;而是根据待排序序列中元素的值来进行排序。 具体的过程如下&#xff1a; 统计序列中每个元素出现的个数&#xff0c;得到一个计数数组count。其中&#xff0c;count[i]表示待排序序列中值…

pandas读写json的知识点

pandas对象可以直接转换为json&#xff0c;使用to_json即可。里面的orient参数很重要&#xff0c;可选值为columns,index,records,values,split,table A B C x 1 4 7 y 2 5 8 z 3 6 9 In [236]: dfjo.to_json(orient"columns") Out[236]: {"A":{"x&qu…

Centos 7rc.local脚本命令开机不执行及指定用户启动的方法

1.开机不启动 在实际生产场景中&#xff0c;我们喜欢在安装了一些软件服务后&#xff0c;将软件设置为开机自启动 配置在/etc/rc.local文件中。直接将软件服务的启动命令写在rc.local文件 注意&#xff1a;编辑完rc.local文件后&#xff0c;一定要给rc.local文件执行权限&#…

exit与return的区别 exit(1)、exit(-1)和exit(0)区别

目录 exit(); 是整个程序的结束。 exit(1)、exit(-1)和exit(0)区别 return();是某个函数的结束&#xff0c;并返回结果。 exit和_exit exit(); 是整个程序的结束。 exit&#xff08;0&#xff09;&#xff1a;正常运行程序并退出程序&#xff1b; exit&#xff08;1&am…

AIGC:使用bert_vits2实现栩栩如生的个性化语音克隆

1 VITS2模型 1.1 摘要 单阶段文本到语音模型最近被积极研究&#xff0c;其结果优于两阶段管道系统。以往的单阶段模型虽然取得了较大的进展&#xff0c;但在间歇性非自然性、计算效率、对音素转换依赖性强等方面仍有改进的空间。本文提出VITS2&#xff0c;一种单阶段的文本到…

Xilinx Kintex7中端FPGA解码MIPI视频,基于MIPI CSI-2 RX Subsystem架构实现,提供工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优缺点4、详细设计方案设计原理框图OV5640及其配置权电阻硬件方案MIPI CSI-2 RX SubsystemSensor Demosaic图像格式转换Gammer LUT伽马校正VDMA图像缓存AXI4-Stream toVideo OutHDMI输出 5、…

Java安全架构 JCA、JCE、JSSE、JAAS

Java语言拥有三大特征&#xff1a;平台无关性、网络移动性和安全性&#xff0c;而Java安全体系结构对这三大特征提供了强大的支持和保证&#xff0c; Java安全体系结构总共分为4个部分&#xff1a; &#xff08;1&#xff09;JCA&#xff08; Java Cryptography Architecture…

工具及方法 - 手机扫条码工具: SCANDIT APP

一般扫个链接使用微信扫一扫即可。扫具体条码&#xff0c;可以在微信里搜索小程序&#xff0c;打开也能扫&#xff0c;得到条码内容。 还有其他方式&#xff0c;比如使用淘宝、百度等APP也可以直接扫码条码&#xff0c;还能得到更多的信息。 使用百度的话&#xff0c;不扫条码…

【洛谷算法题】P5711-闰年判断【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5711-闰年判断【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格式&a…

诡异的bug之dlopen

序 本文给大家分享一个比较诡异的bug&#xff0c;是关于dlopen的&#xff0c;我大致罗列了我项目中使用代码方式及结构&#xff0c;更好的复现这个问题&#xff0c;也帮助大家进一步理解dlopen. 问题复现 以下是项目代码的文件结构&#xff1a; # tree . ├── file1 │ …

2023-11-15 LeetCode每日一题(K 个元素的最大和)

2023-11-15每日一题 一、题目编号 2656. K 个元素的最大和二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你需要执行以下操作 恰好 k 次&#xff0c;最大化你的得分&#xff1a; 从 nums 中选择一个元素 m 。将选中…

【已解决】ModuleNotFoundError: No module named ‘timm‘

问题描述 Traceback (most recent call last): File "main.py", line 48, in <module> import utils File "/media/visionx/monica/project/stable_signature/hidden/utils.py", line 26, in <module> import timm ModuleNotFound…