我正在尝试以递归方式递归生成列表中的所有项目。我已经看到了类似问题的一些解决方案,但我无法让我的代码工作。有人可以指出我如何修复我的代码吗?
这对所有S / O'ers开放,而不仅仅是Java用户。
(另外我应该注意它因SO异常而崩溃)。
示例输入: [1,2,3]
输出: [1,2,3] [1,3,2] [2,1,3] [2,3,1] [3,1,2] [3,2,1]
//allPossibleItems is an AL of all items
//this is called with generatePerm(null, new ArrayList<Item>);
private void generatePerm(Item i, ArrayList<Item> a) {
if(i != null) { a.add(i); }
if (a.size() == DESIRED_SIZE){
permutations.add(a);
return;
}
for(int j = 0; j < allPossibleItems.size(); j ++) {
if(allPossibleItems.get(j) != i)
generatePerm(allPossibleItems.get(j), a);
}
}
答案 0 :(得分:21)
如果allPossibleItems
包含两个不同的元素x和y,那么您将x和y连续写入列表,直到它达到DESIRED_SIZE
。那是你真正想要的吗?如果你选择DESIRED_SIZE
足够大,你将在堆栈上有太多的递归调用,因此SO异常。
我要做的是(如果原版没有重复/重复):
public <E> List<List<E>> generatePerm(List<E> original) {
if (original.size() == 0) {
List<List<E>> result = new ArrayList<List<E>>();
result.add(new ArrayList<E>());
return result;
}
E firstElement = original.remove(0);
List<List<E>> returnValue = new ArrayList<List<E>>();
List<List<E>> permutations = generatePerm(original);
for (List<E> smallerPermutated : permutations) {
for (int index=0; index <= smallerPermutated.size(); index++) {
List<E> temp = new ArrayList<E>(smallerPermutated);
temp.add(index, firstElement);
returnValue.add(temp);
}
}
return returnValue;
}
答案 1 :(得分:2)
问题是在进行递归调用之前必须clone ArrayList。否则,您将始终添加到相同的ArrayList。
//allPossibleItems is an AL of all items
//this is called with generatePerm(null, new ArrayList<Item>);
private void generatePerm(Item i, ArrayList<Item> a) {
if(i != null) { a.add(i); }
if (a.size() == DESIRED_SIZE){
permutations.add(a);
return;
}
for(int j = 0; j < allPossibleItems.size(); j ++) {
if(!a.contains(allPossibleItems.get(j))){
ArrayList<Item> b = clone(a);
generatePerm(allPossibleItems.get(j), b);
}
}
}
答案 2 :(得分:1)
谷歌搜索引导我到这个问题。我发现下面的方法比其他方法更快。
基本上我使用Set来递归生成排列。为了说明,第一个位置可以包含所有可能的值,第二个位置除了第一个值之外的所有可能值,依此类推。当我们到达最后一个位置时,只有一种可能性。
就递归函数的参数而言,(1)我们传递已经记录为currenttring的内容。 (2)我们传递保存结果的Arraylist - list_of_permutes(3)我们通过set来选择当前的数字 - currentnums。 在最后一级,我们有一个完整的排列,然后将其添加到arraylist - list_of_permutes中,然后向上返回。
public static ArrayList permute_array(int[] arr){
Set<Integer> currentnums = new HashSet<>();
for (int i = 0; i < arr.length; i++) {currentnums.add(arr[i]);}
ArrayList permutations = new ArrayList();
recurse_nums(currentnums,"",permutations);
return permutations;
}
可以通过以下方式调用:
Sub CopyFIN() 'copies FIN from account above if E is empty and AJ is anything other than empty
Dim lr As Long
Dim rcell As Range
Dim col As Range
Application.ScreenUpdating = False
lr = Cells(Rows.Count, 6).End(xlUp).Row
Set col = Range("E12:E" & lr)
Set col2 = Range("AJ12:AJ" & lr)
For Each rcell In col2
If rcell.Value <> "" Then
End If
Next
For Each rcell In col
If rcell.Value = "" Then
rcell.Offset(-1, 0).Copy rcell
End If
Next
Application.ScreenUpdating = True
End Sub
答案 3 :(得分:0)
private List generatePerm(List a, int depth) {
// this is the method definition you want
// to generate all permutations, you need cycle thru all elements in your list and for each element
// add that element to each member of generatePerm(a, depth - 1);
// if you want combinations, you need to remove the element and then call
/// generateCombinations with the remaining list
}
答案 4 :(得分:0)
您可以固定起点,然后继续交换。这是最容易理解的方法之一。
public class PermutationListRecursion {
private Set<List<Integer>> permList = new HashSet<>();
public static void main(String[] args) {
PermutationListRecursion pt = new PermutationListRecursion();
Integer[] nums = { 1, 2, 3 };
pt.permute(nums);
System.out.println(pt.permList);
}
public void permute(Integer[] nums) {
permutation(0, nums.length - 1, nums);
}
public void permutation(int start, int end, Integer[] nums) {
if (start == end) {
permList.add(new ArrayList<Integer>(Arrays.asList(nums)));
}
for (int i = start; i <= end; i++) {
permList.add(swap(nums, start, i));
permutation(start + 1, end, nums);
permList.add(swap(nums, start, i));
}
}
private List<Integer> swap(Integer[] arr, int a, int b) {
if (a == b) {
return new ArrayList<>(Arrays.asList(arr));
}
Integer temp = arr[b];
arr[b] = arr[a];
arr[a] = temp;
return new ArrayList<>(Arrays.asList(arr));
}
}
答案 5 :(得分:0)
我调查了此线程,并分析了正确的解决方案。不幸的是,我需要为大量输入使用此递归,这将导致创建很多不需要存储的对象,我想对每个排列应用一个方法,并仅保留那些满足我的算法的对象,因此我想到了这个方法解。希望对别人有帮助。
public static <E> void iteratePermutations(List<E> original, Consumer<List<E>> consumer) {
Objects.requireNonNull(original);
consumer.accept(original);
iteratePermutationsRecursively(original, 0, consumer);
}
public static <E> void iteratePermutationsRecursively(List<E> original, int start, Consumer<List<E>> consumer) {
Objects.requireNonNull(original);
for (int i = start; i < original.size() - 1; i++) {
for (int j = i + 1; j < original.size(); j++) {
List<E> temp = new ArrayList<>(original);
E tempVal = temp.get(i);
temp.set(i, temp.get(j));
temp.set(j, tempVal);
consumer.accept(temp);
iteratePermutationsRecursively(temp, i + 1, consumer);
}
}
}
我可以这样称呼:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<List<Integer>> result = new ArrayList<>();
iteratePermutations(list, result::add);
或:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
iteratePermutations(list, System.out::println);
答案 6 :(得分:0)
输入列表,可能包含重复项。
List<String> list = Arrays.asList("?", "?", "?");
map
方法将列表的每个元素表示为一个置换映射列表。
1: [{0=?}, {1=?}, {2=?}]
2: [{0=?}, {1=?}, {2=?}]
3: [{0=?}, {1=?}, {2=?}]
reduce
方法按顺序对这些列表对求和,并将映射对连接成一个排列映射列表。
{0=?, 1=?, 2=?}
{0=?, 2=?, 1=?}
{1=?, 0=?, 2=?}
{1=?, 2=?, 0=?}
{2=?, 0=?, 1=?}
{2=?, 1=?, 0=?}
public static void main(String[] args) {
// input list
List<String> list = Arrays.asList("?", "?", "?");
// possible permutations
List<Map<Integer, String>> pp = possiblePermutations(list);
// output
pp.forEach(System.out::println);
}
/**
* @param list the input list, may contain duplicates
* @param <E> the type of the element of the list
* @return the list of possible permutations
*/
public static <E> List<Map<Integer, E>> possiblePermutations(List<E> list) {
// check if the list is non-null and non-empty
if (list == null || list.size() == 0) return Collections.emptyList();
return IntStream.range(0, list.size())
// represent each list element as a list of permutation maps
.mapToObj(i -> IntStream.range(0, list.size())
// key - element position, value - element itself
.mapToObj(j -> Collections.singletonMap(j, list.get(j)))
// Stream<List<Map<Integer,E>>>
.collect(Collectors.toList()))
// reduce a stream of lists to a single list
.reduce((list1, list2) -> list1.stream()
.flatMap(map1 -> list2.stream()
// filter out those keys that are already present
.filter(map2 -> map2.keySet().stream()
.noneMatch(map1::containsKey))
// concatenate entries of two maps, order matters
.map(map2 -> new LinkedHashMap<Integer, E>() {{
putAll(map1);
putAll(map2);
}}))
// list of combinations
.collect(Collectors.toList()))
// otherwise an empty collection
.orElse(Collections.emptyList());
}