Golang Go语言中两个面试题求助,有关 slice 和字符串的
Golang Go语言中两个面试题求助,有关 slice 和字符串的
今天被问到两个面试题
1.一个 slice 有 10000 个元素,要删除前面 9999 个,求最佳方案
我答的是取第 10000 个元素的值,新建一个 slice 赋值,之前的 slice 没有引用会被 gc 回收
面试官说这个方案是最差的,因为这样做之前的 slice 依然被引用不会回收,反而增加大量引用效率变差。
这里没理解是为什么,有大佬能讲解一下吗?
2.两个千万级长度的字符串,要比较其中的重复文本出现频率,即相似度,给出解决方案
这题只能想到暴力遍历,没答上来,求大佬给个解决方案
更多关于Golang Go语言中两个面试题求助,有关 slice 和字符串的的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang Go语言中两个面试题求助,有关 slice 和字符串的的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
- 同不懂,我也觉得应该会被回收
2. 如果只是相似度的话,可以做相似度哈希,例如 simdhash
想了下发现第一个问题如果 lz 没有记错了的话,那就是面试官自己有问题
他想测的是 slice 取区间会导致底层的 array 依旧被引用无法释放引发内存泄漏的知识点。比如 s[90:100] 这样取 slice 的区间的话,新生成的 slice 实际上指向的还是原切片 s 的底层数组,所以会引发内存泄漏
但这面试官自己提的问题就有问题,10000 个元素只保留最后一个元素,谁会傻兮兮得用 s[9999:10000] 这种写法,直接 s[9999] 取值赋给新 slice 就行了(也就是 lz 说的这方法),这种方法不会造成内存泄漏,是面试官自己思维定势了。当然面试官可能想说的只是你没提 “需要将原 slice=nil 置 nil” 也有可能
newLen := len(arr[9999:])
copy(arr[0:newLen], arr[9999:])
arr = arr[0:newLen]
可能是要重复利用底层的数组吧,避免后续频繁申请和释放底层数组的内存
https://go.dev/play/p/ETH4u-QfgtN
第二题是寻找最长子序列吗
请教个问题,如果不将原 slice=nil ,gc 不会正常回收这部分内存吗?不是已经没有到原 slice 的引用了吗?
引用原 slice 的变量不置 nil ,不还是被原变量引用着吗,就算你没用到
谢谢 应该就是当时表达的问题,我就是觉得我对这个的理解应该没错啊
谢谢 我去看看这个
现在面试都已经这么卷了吗…真不敢想象
- 应该是
s[0] = s[9999]; s = s[1:]
吧
当然,我很乐意帮助你解答关于Go语言中slice和字符串的面试题。
-
关于slice的问题:
- 描述slice的底层结构:Slice在Go中是一个抽象数据结构,包含三个字段:指向数组的指针(Pointer)、切片的长度(Length)和切片的容量(Capacity)。Slice本身不存储数据,只是对一个已存在数组的引用。
- slice的扩容机制:当向slice追加元素且容量不足时,Go会分配一个更大的底层数组,将旧数组的数据复制到新数组中,并更新slice的指针和长度。扩容策略通常是按倍数增长(如1.25倍),以减少频繁扩容带来的性能开销。
-
关于字符串的问题:
- 字符串的不可变性:在Go中,字符串是不可变的。这意味着一旦字符串被创建,其内容就不能被改变。如果需要修改字符串,通常会创建一个新的字符串。
- 字符串与字节切片([]byte)的转换:可以通过显式转换将字符串转换为字节切片(
[]byte(str)
),反之亦然(string(b)
)。这种转换是高效的,因为底层数据是共享的,除非进行写操作导致数据拷贝。
希望这些回答能帮助你更好地理解Go语言中的slice和字符串。如果你有更具体的问题或需要进一步的解释,请随时提问。