面试题答案
一键面试- 预分配容量:
- Go语言切片在容量不足时会进行扩容,扩容操作涉及内存的重新分配和数据的拷贝,开销较大。对于大规模切片,在初始化时尽量准确预估其最大容量,使用
make
函数预分配足够的容量。例如:
// 预分配1000个元素的容量 s := make([]int, 0, 1000)
- Go语言切片在容量不足时会进行扩容,扩容操作涉及内存的重新分配和数据的拷贝,开销较大。对于大规模切片,在初始化时尽量准确预估其最大容量,使用
- 减少内存拷贝:
- 在删除元素时,尽量避免直接使用
append
重新构建切片,而是采用移动元素的方式。例如,删除切片s
中索引为i
的元素,可以这样做:
s = append(s[:i], s[i+1:]...)
- 这种方式会导致后续元素的移动,但相比重新构建切片,减少了一次内存拷贝。
- 在删除元素时,尽量避免直接使用
- 使用双端队列(模拟):
- Go标准库没有直接提供双端队列的数据结构,但可以通过切片模拟。对于频繁的插入和删除操作,如果主要在切片头部和尾部进行,可以自己实现一个类似双端队列的结构,减少中间插入删除带来的元素移动开销。例如:
type Deque struct { data []int head int tail int } func NewDeque(capacity int) *Deque { return &Deque{ data: make([]int, capacity), head: 0, tail: 0, } } func (d *Deque) PushFront(x int) { d.head = (d.head - 1 + len(d.data)) % len(d.data) d.data[d.head] = x } func (d *Deque) PushBack(x int) { d.data[d.tail] = x d.tail = (d.tail + 1) % len(d.data) } func (d *Deque) PopFront() int { x := d.data[d.head] d.head = (d.head + 1) % len(d.data) return x } func (d *Deque) PopBack() int { d.tail = (d.tail - 1 + len(d.data)) % len(d.data) return d.data[d.tail] }
- 分批操作:
- 如果可能,将多个插入或删除操作合并成一批处理。这样可以减少多次扩容或元素移动的次数。例如,将多个插入操作收集到一个临时切片中,然后一次性
append
到主切片:
temp := []int{1, 2, 3} s = append(s, temp...)
- 如果可能,将多个插入或删除操作合并成一批处理。这样可以减少多次扩容或元素移动的次数。例如,将多个插入操作收集到一个临时切片中,然后一次性