如何有效地从Kotlin中的集合(前N个)中获取N个最低值?
如何有效地从Kotlin中的集合(前N个)中获取N个最低值 除了{it.value}.take(n)之外,还有其他方法吗如何有效地从Kotlin中的集合(前N个)中获取N个最低值?,kotlin,Kotlin,如何有效地从Kotlin中的集合(前N个)中获取N个最低值 除了{it.value}.take(n)之外,还有其他方法吗 假设我有一个包含+100500个元素的集合,我需要找到10个最低的元素。我担心由分类的将创建新的临时收集,以后只需要10件物品。您需要担心的更多 collectionOrSequence.sortedby{it.value}运行java.util.Arrays.sort,该操作将运行timSort(或mergeSort,如果请求) 很好,但通常以n*log(n)操作结束,这
假设我有一个包含+100500个元素的集合,我需要找到10个最低的元素。我担心由分类的
将创建新的临时收集,以后只需要10件物品。您需要担心的更多
collectionOrSequence.sortedby{it.value}
运行java.util.Arrays.sort
,该操作将运行timSort(或mergeSort,如果请求)
- 很好,但通常以n*log(n)操作结束,这远远超过复制数组的O(n)
- 每个O(n*log.n)操作都将运行一个函数(您提供的lambda,
{it.value}
)-->,这将带来额外的有意义的开销
- 最后,
java.util.Array.sort
将集合转换为数组并返回到列表-另外两种转换(您希望避免,但这是次要的)
有效的方法可能是:
将要比较的值映射到一个列表中:O(n)个转换(每个元素一次),而不是O(n*log.n)或更多
在创建的列表(或数组)上迭代,以在一次过程中收集N个最小的元素
- 将迄今为止发现的N个最小元素及其索引保留在原始列表中。如果它很小(例如10项)-
mutableList
非常适合
- 为小元素列表保留一个保持最大值的变量
- 迭代原始集合时,将原始列表上的当前元素与小值列表的最大值进行比较。如果小于它-在“小列表”中替换它,并在其中找到更新的最大值
使用“小列表”中的索引提取原始列表中的10个最小元素
这将允许您从O(n*log.n)转到O(n)
当然,如果时间很关键,那么最好对具体案例进行基准测试
如果您在第一步设法提取原语以进行比较(例如,int
或long
),则效率会更高。您需要担心的问题更多
collectionOrSequence.sortedby{it.value}
运行java.util.Arrays.sort
,该操作将运行timSort(或mergeSort,如果请求)
- 很好,但通常以n*log(n)操作结束,这远远超过复制数组的O(n)
- 每个O(n*log.n)操作都将运行一个函数(您提供的lambda,
{it.value}
)-->,这将带来额外的有意义的开销
- 最后,
java.util.Array.sort
将集合转换为数组并返回到列表-另外两种转换(您希望避免,但这是次要的)
有效的方法可能是:
将要比较的值映射到一个列表中:O(n)个转换(每个元素一次),而不是O(n*log.n)或更多
在创建的列表(或数组)上迭代,以在一次过程中收集N个最小的元素
- 将迄今为止发现的N个最小元素及其索引保留在原始列表中。如果它很小(例如10项)-
mutableList
非常适合
- 为小元素列表保留一个保持最大值的变量
- 迭代原始集合时,将原始列表上的当前元素与小值列表的最大值进行比较。如果小于它-在“小列表”中替换它,并在其中找到更新的最大值
使用“小列表”中的索引提取原始列表中的10个最小元素
这将允许您从O(n*log.n)转到O(n)
当然,如果时间很关键,那么最好对具体案例进行基准测试
如果您在第一步设法提取原语作为比较的基础(例如int
或long
),则效率更高。您可以保留n个最小元素的列表,并根据需要进行更新,例如
fun <T : Comparable<T>> top(n: Int, collection: Iterable<T>): List<T> {
return collection.fold(ArrayList<T>()) { topList, candidate ->
if (topList.size < n || candidate < topList.last()) {
// ideally insert at the right place
topList.add(candidate)
topList.sort()
// trim to size
if (topList.size > n)
topList.removeAt(n)
}
topList
}
}
fun top(n:Int,collection:Iterable):列表{
return collection.fold(ArrayList()){topList,candidate->
if(topList.sizen)
topList.removeAt(n)
}
排行榜
}
}
这样,您只需将列表中的当前元素与前n个元素中的最大元素进行一次比较,这通常比对整个列表进行排序要快您可以保留一个包含n个最小元素的列表,并根据需要进行更新,例如
fun <T : Comparable<T>> top(n: Int, collection: Iterable<T>): List<T> {
return collection.fold(ArrayList<T>()) { topList, candidate ->
if (topList.size < n || candidate < topList.last()) {
// ideally insert at the right place
topList.add(candidate)
topList.sort()
// trim to size
if (topList.size > n)
topList.removeAt(n)
}
topList
}
}
fun top(n:Int,collection:Iterable):列表{
return collection.fold(ArrayList()){topList,candidate->
if(topList.sizen)
topList.removeAt(n)
}
榜单
}
}
这样,您只需将列表中的当前元素与前n个元素中的最大元素进行一次比较,这通常比对整个列表进行排序要快我建议根据典型的快速排序算法(按降序,并取前n个元素)实现您自己的排序方法,如果集合中有1k+值随机分布。如果集合中有1k+值随机分布,我建议基于典型的快速排序算法(按降序,并取前N个元素)实现您自己的排序方法。如果您在JVM上运行,您可以