我喜欢用Python处理列表的方式。它做任何递归解决方案看起来容易和干净。例如,在Python中获取元素的所有排列的典型问题如下所示:
def permutation_recursion(numbers,sol):
if not numbers:
print "this is a permutation", sol
for i in range(len(numbers)):
permutation_recursion(numbers[:i] + numbers[i+1:], sol + [numbers[i]])
def get_permutations(numbers):
permutation_recursion(numbers,list())
if __name__ == "__main__":
get_permutations([1,2,3])
我喜欢通过这样的方式简单地获取修改后的列表的新实例的方式
numbers[:i] + numbers[i+1:]
或sol + [numbers[i]]
如果我尝试在Java中编写完全相同的代码,它看起来像:
import java.util.ArrayList;
import java.util.Arrays;
class rec {
static void permutation_recursion(ArrayList<Integer> numbers, ArrayList<Integer> sol) {
if (numbers.size() == 0)
System.out.println("permutation="+Arrays.toString(sol.toArray()));
for(int i=0;i<numbers.size();i++) {
int n = numbers.get(i);
ArrayList<Integer> remaining = new ArrayList<Integer>(numbers);
remaining.remove(i);
ArrayList<Integer> sol_rec = new ArrayList<Integer>(sol);
sol_rec.add(n);
permutation_recursion(remaining,sol_rec);
}
}
static void get_permutation(ArrayList<Integer> numbers) {
permutation_recursion(numbers,new ArrayList<Integer>());
}
public static void main(String args[]) {
Integer[] numbers = {1,2,3};
get_permutation(new ArrayList<Integer>(Arrays.asList(numbers)));
}
}
要创建我需要做的相同递归:
ArrayList<Integer> remaining = new ArrayList<Integer>(numbers);
remaining.remove(i);
ArrayList<Integer> sol_rec = new ArrayList<Integer>(sol);
sol_rec.add(n);
这对于更复杂的解决方案而言非常难看。就像this example
一样所以我的问题是...... Java API中是否有任何内置运算符或辅助函数可以使这个解决方案更“Pythonic”?
答案 0 :(得分:8)
没有。
但这就是Martin Odersky创造Scala的原因。他甚至说他对Scala的目标之一就是它是Java世界的Python。 Scala编译为Java字节码,并且可以轻松地与Java编译类进行交互。
如果这不是一个选项,您可以查看Commons Collection Library。
答案 1 :(得分:2)
您可以使用列表上的clone()
函数来获取它们的浅表副本。这样你就不必自己实例化一个新的对象,但只能使用副本。
ArrayList<Integer> remaining = remaining.clone().remove(i);
除此之外,不,java没有列表的运算符。
答案 2 :(得分:1)
Apache Commons解决了很多这类问题。看看ArrayUtils做切片。由于各种原因,Java没有像脚本语言那样的大量语法糖。
答案 3 :(得分:1)
不同的语言需要不同的风格。尝试在java中完成mylist[:i] + mylist[i+1:]
就像使用带螺丝的锤子一样。是的,你可以做到,但它不是很整洁。我相信等价物可能类似于ArrayList temp = new ArrayList(list); temp.remove(index);
我相信以下内容可以完成相同的任务,但是会以稍微不同的方式完成,但不会出现可读性问题。它不是创建新列表,而是修改列表,传递它,并在递归调用返回时将列表返回到先前的状态。
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class Permutation {
public static void main(String[] args) {
List<List<Integer>> result = permutations(
Arrays.asList(
new Integer[] {1,2,3}));
for (List<Integer> permutation : result) {
System.out.println(permutation);
}
}
public static <T> List<List<T>> permutations(List<T> input) {
List<List<T>> out = new ArrayList<List<T>>();
permutationsSlave(input, new ArrayList<T>(), out);
return out;
}
public static <T> void permutationsSlave(List<T> input,
ArrayList<T> permutation, List<List<T>> result) {
if (input.size() == chosen.size()) {
result.add(new ArrayList<T>(permutation));
return;
}
for (T obj : input) {
if (!permutation.contains(obj)) {
permutation.add(obj);
permutationsSlave(input, permutation, result);
permutation.remove(permutation.size()-1);
}
}
}
}
python方式可能看起来更简单,更清晰,但看起来干净的能力通常会隐藏这样一个事实:解决方案效率非常低(对于每个级别的递归,它会创建5个新列表)。
但是我自己的解决方案也不是非常有效 - 它不是创建多个新对象而是执行冗余比较(尽管可以通过使用累加器来缓解一些)。
答案 4 :(得分:0)
您好 1你可以使用堆栈,这将更方便。
2 for循环可以这样写: for(Number n:numbers)