我想用一个示例程序来展示它:
private static List<List> subn(int n, List li) {
List<List> ret = new ArrayList<List>();
if (n == 0) {
ret.add(new ArrayList());
return ret;
}
if (li.isEmpty()) {
return ret;
}
T x = li.get(0);
List xs = li.subList(1, li.size());
for (List sub : subn(n-1, xs)) {
sub.add(0, x);
ret.add(sub);
}
ret.addAll(subn(n, xs));
return ret;
}
第一步我想删除静态类型,虽然我不反对它,但对于这么小的代码,我会去的。
def subn(n, li) {
def ret = new ArrayList();
if (n == 0) {
ret.add(new ArrayList());
return ret;
}
if (li.isEmpty()) {
return ret;
}
def x = li.get(0);
def xs = li.subList(1, li.size());
for (sub in subn(n-1, xs)) {
sub.add(0, x);
ret.add(sub);
}
ret.addAll(subn(n, xs));
return ret;
}
这将改变字符数:) 但不会改变结构。
现在让我们更改数组文字:
def subn(n, li) {
def ret = [];
if (n == 0) {
ret.add([]);
return ret;
}
if (li.isEmpty()) {
return ret;
}
def x = li.get(0);
def xs = li.subList(1, li.size());
for (sub in subn(n-1, xs)) {
sub.add(0, x);
ret.add(sub);
}
ret.addAll(subn(n, xs));
return ret;
}
我们看到更多的字符被修剪,现在让我们更改 if 语句。
def subn(n, li) {
if (n == 0) return [[]];
if (li.isEmpty()) return [];
def ret = [];
def x = li.get(0);
def xs = li.subList(1, li.size());
for (sub in subn(n-1, xs)) {
sub.add(0, x);
ret.add(sub);
}
ret.addAll(subn(n, xs));
return ret;
}
我不太喜欢短变量名,所以下一步是重命名一些变量。除此之外,我将稍微更改循环以使用 each 函数。 “it”魔术变量替换了“sub”变量。
def subn(n, list) {
if (n == 0) return [[]];
if (list.isEmpty()) return [];
def ret = [];
def head = list.get(0);
def remainder = list.subList(1, list.size());
subn(n-1, remainder).each {
it.add(0, head);
ret.add(it);
}
ret.addAll(subn(n, remainder));
return ret;
}
通过将集合相加,我们可以进一步简化循环:
def subn(n, list) {
if (n == 0) return [[]];
if (list.isEmpty()) return [];
def ret = [];
def head = list.get(0);
def remainder = list.subList(1, list.size());
subn(n-1, remainder).each {
ret.add([head] + it);
}
ret.addAll(subn(n, remainder));
return ret;
}
查看代码很明显,“ret”变量只是在累积结果。为此,我们可以使用 collect 方法。
def subn(n, list) {
if (n == 0) return [[]];
if (list.isEmpty()) return [];
def head = list.get(0);
def remainder = list.subList(1, list.size());
def ret = subn(n-1, remainder).collect { [head] + it }
ret.addAll(subn(n, remainder));
return ret;
}
事实上,如果我们只是将两个集合加在一起,我们真的根本不需要“ret”:
def subn(n, list) {
if (n == 0) return [[]];
if (list.isEmpty()) return [];
def head = list.get(0);
def remainder = list.subList(1, list.size());
return subn(n-1, remainder).collect { [head] + it } + subn(n, remainder);
}
最后让内联 head 变量。反正它只用在一个地方,所以不值得保留。此外,我们将使用 Groovy 列表索引来删除 get() 调用。
def subn(n, list) {
if (n == 0) return [[]];
if (list.isEmpty()) return [];
def remainder = list.subList(1, list.size());
return subn(n-1, remainder).collect { [list[ 0 ]] + it } + subn(n, remainder);
}