将元素插入排序切片的最有效方法是什么?
我尝试了几件事,但最后都使用了至少2个附加内容,据我所知,这是一个新的切片副本
答案 0 :(得分:5)
如果切片有足够的容量,则不需要新的副本。 插入位置后的元素可以向右移动。 只有当切片没有足够的容量时, 一个新的切片并复制所有值是必要的。
请注意,切片不是为快速插入而设计的。 因此,使用切片不会成为奇迹解决方案。 您可以创建自定义数据结构以提高效率, 但显然会有其他权衡因素。
在此过程中可以优化的一点是快速找到插入点。如果切片已排序,则可以使用二进制搜索在O(log n)
时间内执行此操作。
但是,这可能并不重要,
考虑到复制切片末端的昂贵操作,
或在必要时重新分配。
答案 1 :(得分:0)
以下是如何插入排序后的字符串片段:
转到Playground链接至完整示例:https://play.golang.org/p/4RkVgEpKsWq
func Insert(ss []string, s string) []string {
i := sort.SearchStrings(ss, s)
ss = append(ss, "")
copy(ss[i+1:], ss[i:])
ss[i] = s
return ss
}
答案 2 :(得分:0)
播放:https://play.golang.org/p/dUGmPurouxA
array1 := []int{1, 3, 4, 5}
//want to insert at index 1
insertAtIndex := 1
temp := append([]int{}, array1[insertAtIndex:]...)
array1 = append(array1[0:insertAtIndex], 2)
array1 = append(array1, temp...)
fmt.Println(array1)
答案 3 :(得分:0)
你可以使用堆:
package main
import (
"container/heap"
"sort"
)
type slice struct { sort.IntSlice }
func (s slice) Pop() interface{} { return 0 }
func (s *slice) Push(x interface{}) {
(*s).IntSlice = append((*s).IntSlice, x.(int))
}
func main() {
s := &slice{
sort.IntSlice{11, 10, 14, 13},
}
heap.Init(s)
heap.Push(s, 12)
println(s.IntSlice[0] == 10)
}
注意堆不是严格排序的,但保证“最小元素”
成为第一个元素。我也没有在我的中实现 Pop
函数
例如,你会想要这样做。
答案 4 :(得分:0)
问题有两部分:找到插入值的位置和插入值。
使用 sort package 搜索函数通过二分搜索高效地找到插入索引。
使用一次对 append
的调用可以有效地将值插入到切片中:
// insertAt inserts v into s at index i and returns the new slice.
func insertAt(data []int, i int, v int) []int {
if i == len(data) {
// Insert at end is the easy case.
return append(data, v)
}
// Make space for the inserted element by shifting
// values at the insertion index up one index. The call
// to append does not allocate memory when cap(data) is
// greater than len(data).
data = append(data[:i+1], data[i:]...)
// Insert the new element.
data[i] = v
// Return the updated slice.
return data
}
以下是在排序后的切片中插入值的代码:
func insertSorted(data []int, v int) []int {
i := sort.Search(len(data), func(i int) bool { return data[i] >= v })
return insertAt(data, i, v)
}
此答案中的代码使用了 int
的一部分。调整类型以匹配您的实际数据。
此答案中对 sort.Search 的调用可以替换为对辅助函数 sort.SearchInts 的调用。我在这个答案中显示 sort.Search 因为该函数适用于任何类型的切片。
如果不想添加重复值,请在插入前检查搜索索引处的值:
func insertSortedNoDups(data []int, v int) []int {
i := sort.Search(len(data), func(i int) bool { return data[i] >= v })
if i < len(data) && data[i] == v {
return data
}
return insertAt(data, i, v)
}