在Groovy中输出子序列列表和子序列列表的最有效方法是什么?

在Groovy中输出子序列列表和子序列列表的最有效方法是什么?,groovy,Groovy,我正在尝试编写一个方法,以便在Groovy中输出子序列列表和反向对应项 这是我当前的代码: LinkedHashSet subsequencesAndReversedOfList(List l, Integer max = null) { def output = ( max == null ) ? l.subsequences() : l.subsequences().findAll { it.size() == max } def reversedOutput = []

我正在尝试编写一个方法,以便在Groovy中输出子序列列表和反向对应项

这是我当前的代码:

LinkedHashSet subsequencesAndReversedOfList(List l, Integer max = null) {
    def output = ( max == null ) ? l.subsequences() : l.subsequences().findAll { it.size() == max }
    def reversedOutput = []
    output.each { reversedOutput << it.reverse() }
    output += reversedOutput
    output
}
它输出:

Raisin Fruit
Raisin Nut
Raisin Apple
Apple Walnut
Apple Pommes
Raisin Walnut
Fruit Walnut
Fruit Apple
Raisin Pommes
Fruit Nut
Nut Walnut
Pommes Walnut
Pommes Nut
Fruit Pommes
Apple Nut
Fruit Raisin
Nut Raisin
Apple Raisin
Walnut Apple
Pommes Apple
Walnut Raisin
Walnut Fruit
Apple Fruit
Pommes Raisin
Nut Fruit
Walnut Nut
Walnut Pommes
Nut Pommes
Pommes Fruit
Nut Apple
这是我正在寻找的输出。这是最有效的方法吗?

您可以:

LinkedHashSet subsequencesAndReversedOfList(List list, Integer max = null) {
    list.subsequences().findAll { max == null || it.size() == max }
        .with {
            it + it*.reverse()
        }
}
哪一种方法更有效,因为你需要花更少的时间打字

“效率更高”是什么意思?

您可以:

LinkedHashSet subsequencesAndReversedOfList(List list, Integer max = null) {
    list.subsequences().findAll { max == null || it.size() == max }
        .with {
            it + it*.reverse()
        }
}
哪一种方法更有效,因为你需要花更少的时间打字


“效率更高”是什么意思?

在一个大列表中,丢弃大多数元素的成本是很高的=O(n³)


您不应该使用
子序列()
。您可以在一个大列表中构建一个O(n²)实现

。丢弃大多数元素的成本很高=O(n³)


您不应该使用
子序列()
。您可以构建O(n²)实现

对于解决方案的第一部分,您应该替换O(n³)复杂性表达式:

l.subsequences().findAll { it.size() == max }
以下O(n²)计算以所需的组合大小为目标,仅计算所需的大小:

def comb
comb = { m, list ->
    def n = list.size()
    m == 0
        ? [[]]
        : (0..(n-m)).inject([]) { newlist, k ->
            newlist += comb(m-1, list[(k+1)..<n]).collect { [list[k]] + it }
        }
}
不过,此实现确实有很大的开销,因此它实际上无法与基于Groovy
List.subsequences()
的实现进行竞争,并进行后续过滤,直到出现两种情况(程度不同):

  • 最终结果中的项目数很小(仅当
    max
    非常小或
    max
    接近基本列表的大小时才会发生这种情况)
  • 基本列表的大小很大

在我的基准测试中,我的目标解决方案总是比原始筛选解决方案慢,直到列表大小达到
11
。此时,针对
1
2
3
10
11
等“边缘”值的
max
值,目标解决方案的速度更快。但是,当列表大小达到
20
时,除了
10
11
这两个最中间的值之外,所有
max
值的目标解决方案都要快得多。

对于解决方案的第一部分,您应该替换O(n³)复杂度表达式:

l.subsequences().findAll { it.size() == max }
以下O(n²)计算以所需的组合大小为目标,仅计算所需的大小:

def comb
comb = { m, list ->
    def n = list.size()
    m == 0
        ? [[]]
        : (0..(n-m)).inject([]) { newlist, k ->
            newlist += comb(m-1, list[(k+1)..<n]).collect { [list[k]] + it }
        }
}
不过,此实现确实有很大的开销,因此它实际上无法与基于Groovy
List.subsequences()
的实现进行竞争,并进行后续过滤,直到出现两种情况(程度不同):

  • 最终结果中的项目数很小(仅当
    max
    非常小或
    max
    接近基本列表的大小时才会发生这种情况)
  • 基本列表的大小很大

在我的基准测试中,我的目标解决方案总是比原始筛选解决方案慢,直到列表大小达到
11
。此时,针对
1
2
3
10
11
等“边缘”值的
max
值,目标解决方案的速度更快。然而,当列表大小达到
20
时,除了
10
11
这两个最中间的值之外,所有
max
值的目标解决方案都要快得多。

我喜欢您解决方案的优雅。我说的“更高效”是指计算速度更快。我喜欢你的解决方案的优雅。我所说的“更高效”是指计算速度更快。