java列表分区,在Java中查找集合的所有分区

小编典典

您非常接近正确的答案。您说您正在获得无限递归,但实际上程序在最外层循环中以无限循环运行。

与Python代码的主要区别在于,i在Python版本中,变量始终在外循环中前进,但是在Java版本中,i >>=

1内循环内的语句始终保留i为零。解决此问题的简单方法是对内部和外部循环使用单独的变量。

通常,这就是为什么尝试直接将程序从一种语言翻译成另一种语言是个坏主意的原因。几乎每个程序都有一些在原始语言中有意义的惯用语,这些惯用语在目标语言中将是古怪的或毫无意义的。特别地,Python代码依赖于隐式提升为任意精度整数的正确性。这在Java中不能很好地工作,因此,如果输入集大于31个元素,则以下实现会遭受整数溢出的困扰。您的示例只有4个元素,因此对于这种特定情况,它将产生正确的答案。

这是更正后的Java版本:

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

public class Partition {

private static List>> partitions(List inputSet) {

List>> res = new ArrayList<>();

if (inputSet.isEmpty()) {

List> empty = new ArrayList<>();

res.add(empty);

return res;

}

// Note that this algorithm only works if inputSet.size() < 31

// since you overflow int space beyond that. This is true even

// if you use Math.pow and cast back to int. The original

// Python code does not have this limitation because Python

// will implicitly promote to a long, which in Python terms is

// an arbitrary precision integer similar to Java's BigInteger.

int limit = 1 << (inputSet.size() - 1);

// Note the separate variable to avoid resetting

// the loop variable on each iteration.

for (int j = 0; j < limit; ++j) {

List> parts = new ArrayList<>();

List part1 = new ArrayList<>();

List part2 = new ArrayList<>();

parts.add(part1);

parts.add(part2);

int i = j;

for (String item : inputSet) {

parts.get(i&1).add(item);

i >>= 1;

}

for (List> b : partitions(part2)) {

List> holder = new ArrayList<>();

holder.add(part1);

holder.addAll(b);

res.add(holder);

}

}

return res;

}

public static void main(String[] args) {

for (List> partitions :

partitions(Arrays.asList("a", "b", "c", "d"))) {

System.out.println(partitions);

}

}

}

这是我的Java版本的输出:

[[a, b, c, d]]

[[b, c, d], [a]]

[[a, c, d], [b]]

[[c, d], [a, b]]

[[c, d], [b], [a]]

[[a, b, d], [c]]

[[b, d], [a, c]]

[[b, d], [c], [a]]

[[a, d], [b, c]]

[[a, d], [c], [b]]

[[d], [a, b, c]]

[[d], [b, c], [a]]

[[d], [a, c], [b]]

[[d], [c], [a, b]]

[[d], [c], [b], [a]]

2020-07-28

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值