递归代替多重循环

发布于 2024-07-08 02:54:34 字数 648 浏览 8 评论 0原文

我希望这个方法适用于任何给定数量的参数,我可以通过代码生成来做到这一点(有很多丑陋的代码),它可以通过递归来完成吗? 如果是这样怎么办? 我理解递归,但我不知道如何写这个。

private static void allCombinations(List<String>... lists) {
    if (lists.length == 3) {
        for (String s3 : lists[0]) {
            for (String s1 : lists[1]) {
                for (String s2 : lists[2]) {
                    System.out.println(s1 + "-" + s2 + "-" + s3);
                }
            }
        }
    }
    if (lists.length == 2) {
        for (String s3 : lists[0]) {
            for (String s1 : lists[1]) {
                    System.out.println(s1 + "-" + s3);
            }
        }
    }
}

I want this method to work for any given number of arguments, i can do that with code generation(with a lot of ugly code), can it be done with recursion? if so how? I understand recursion, but i dont know how to write this.

private static void allCombinations(List<String>... lists) {
    if (lists.length == 3) {
        for (String s3 : lists[0]) {
            for (String s1 : lists[1]) {
                for (String s2 : lists[2]) {
                    System.out.println(s1 + "-" + s2 + "-" + s3);
                }
            }
        }
    }
    if (lists.length == 2) {
        for (String s3 : lists[0]) {
            for (String s1 : lists[1]) {
                    System.out.println(s1 + "-" + s3);
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

故人爱我别走 2024-07-15 02:54:34

这是一个简单的递归实现:

private static void allCombinations(List<String>... lists) {
  allCombinations(lists, 0, "");
}

private static void allCombinations(List<String>[] lists, int index, String pre) {
  for (String s : lists[index]) {
    if (index < lists.length - 1) {
      allCombinations(lists, index + 1, pre + s + "-");
    }else{
      System.out.println(pre + s);
    }
  }
}

Here is a simple recursive implementation:

private static void allCombinations(List<String>... lists) {
  allCombinations(lists, 0, "");
}

private static void allCombinations(List<String>[] lists, int index, String pre) {
  for (String s : lists[index]) {
    if (index < lists.length - 1) {
      allCombinations(lists, index + 1, pre + s + "-");
    }else{
      System.out.println(pre + s);
    }
  }
}
南城旧梦 2024-07-15 02:54:34

你特别需要它是递归的吗? 我会将其设为非递归,但仍然不是特殊情况:

public static void allCombinations(List<String>... lists) {
    int[] indexes = new int[lists.length];

    while (incrementIndexes(lists, indexes)) {
        StringBuilder builder = new StringBuilder();
        for (int i=0; i < indexes.length; i++) {
            if (i != 0) {
                builder.append("-");
            }
            builder.append(lists[i].get(indexes[i]));
        }
        System.out.println(builder);
    }
}

private static boolean incrementIndexes(List<String>[] lists, int[] indexes) {
    for (int depth = indexes.length-1; depth >= 0; depth--) {
        indexes[depth]++;
        if (indexes[depth] != lists[depth].size()) {
            return true;
        }
        // Overflowed this index. Reset to 0 and backtrack
        indexes[depth] = 0;
    }
    // Everything is back to 0. Finished!
    return false;
}

Do you particularly need it to be recursive? I'd make it non-recursive but still not special case things:

public static void allCombinations(List<String>... lists) {
    int[] indexes = new int[lists.length];

    while (incrementIndexes(lists, indexes)) {
        StringBuilder builder = new StringBuilder();
        for (int i=0; i < indexes.length; i++) {
            if (i != 0) {
                builder.append("-");
            }
            builder.append(lists[i].get(indexes[i]));
        }
        System.out.println(builder);
    }
}

private static boolean incrementIndexes(List<String>[] lists, int[] indexes) {
    for (int depth = indexes.length-1; depth >= 0; depth--) {
        indexes[depth]++;
        if (indexes[depth] != lists[depth].size()) {
            return true;
        }
        // Overflowed this index. Reset to 0 and backtrack
        indexes[depth] = 0;
    }
    // Everything is back to 0. Finished!
    return false;
}
北城孤痞 2024-07-15 02:54:34

这是一个通用的递归版本。 它抱怨测试代码中未经检查的通用数组创建,但排列代码本身没问题:

import java.util.*;

public class Test
{
    public interface Action<T> {
        void execute(Iterable<T> values);
    }

    public static void main(String[] args) {
        List<String> first = Arrays.asList(new String[]{"1", "2", "3"});
        List<String> second = Arrays.asList(new String[]{"a", "b", "c"});
        List<String> third = Arrays.asList(new String[]{"x", "y"});
        Action<String> action = new Action<String>() {
            @Override public void execute(Iterable<String> values) {
                 StringBuilder builder = new StringBuilder();
                 for (String value : values) {
                     if (builder.length() != 0) {
                         builder.append("-");
                     }
                     builder.append(value);
                 }
                 System.out.println(builder);
            }
        };
        permute(action, first, second, third);
    }

    public static <T> void permute(Action<T> action, Iterable<T>... lists) {
        Stack<T> current = new Stack<T>();
        permute(action, lists, 0, current);
    }

    public static <T> void permute(Action<T> action, Iterable<T>[] lists,
        int index, Stack<T> current) {
        for (T element : lists[index]) {
            current.push(element);
            if (index == lists.length-1) {
              action.execute(current);
            } else {
              permute(action, lists, index+1, current);
            }
            current.pop();
        }
    }
}

Here's a generalised recursive version. It complains about unchecked generic array creation in the test code, but the permute code itself is okay:

import java.util.*;

public class Test
{
    public interface Action<T> {
        void execute(Iterable<T> values);
    }

    public static void main(String[] args) {
        List<String> first = Arrays.asList(new String[]{"1", "2", "3"});
        List<String> second = Arrays.asList(new String[]{"a", "b", "c"});
        List<String> third = Arrays.asList(new String[]{"x", "y"});
        Action<String> action = new Action<String>() {
            @Override public void execute(Iterable<String> values) {
                 StringBuilder builder = new StringBuilder();
                 for (String value : values) {
                     if (builder.length() != 0) {
                         builder.append("-");
                     }
                     builder.append(value);
                 }
                 System.out.println(builder);
            }
        };
        permute(action, first, second, third);
    }

    public static <T> void permute(Action<T> action, Iterable<T>... lists) {
        Stack<T> current = new Stack<T>();
        permute(action, lists, 0, current);
    }

    public static <T> void permute(Action<T> action, Iterable<T>[] lists,
        int index, Stack<T> current) {
        for (T element : lists[index]) {
            current.push(element);
            if (index == lists.length-1) {
              action.execute(current);
            } else {
              permute(action, lists, index+1, current);
            }
            current.pop();
        }
    }
}
十二 2024-07-15 02:54:34

这是我基于 Rasmus 解决方案的具有正确排序的递归解决方案。 仅当所有列表的大小相同时它才有效。

import java.util.Arrays;
import java.util.List;


public class Test {

        public static void main(String[] args) {
        List<String> first = Arrays.asList(new String[]{"1", "2", "3"});
        List<String> second = Arrays.asList(new String[]{"a", "b", "c"});
        List<String> third = Arrays.asList(new String[]{"x", "y", "z"});
        allCombinations (first, second, third);
        }

        private static void allCombinations(List<String>... lists) {
              allCombinations(lists, 1, "");
        }

        private static void allCombinations(List<String>[] lists, int index, String pre) {
            int nextHop = hop(index, lists.length-1);
          for (String s : lists[index]) {
            if (index != 0) {
              allCombinations(lists, nextHop, pre + s + "-");
            } else System.out.println(pre + s);
          }
        }
        private static int hop(int prevIndex, int maxResult){
            if (prevIndex%2 == 0){
                return prevIndex-2;
            } else {
                if (prevIndex == maxResult) 
                    return prevIndex-1;
                int nextHop = prevIndex+2;
                if (nextHop > maxResult){
                    return maxResult;
                } else return nextHop;
            }
        }

}

允许不同大小的列表的“正确排序”解决方案必须从最后一个列表开始,并向后运行到第一个列表(lists[0]),将元素附加在“pre”字符串的开头或结尾并继续传递它。 同样,第一个列表将打印结果。 我本想编码的,但是午餐已经准备好了,女朋友开始不喜欢 stackoverflow 了……

here's my recursive solution with correct ordering, based on Rasmus' solution. it works only if all lists are of same size.

import java.util.Arrays;
import java.util.List;


public class Test {

        public static void main(String[] args) {
        List<String> first = Arrays.asList(new String[]{"1", "2", "3"});
        List<String> second = Arrays.asList(new String[]{"a", "b", "c"});
        List<String> third = Arrays.asList(new String[]{"x", "y", "z"});
        allCombinations (first, second, third);
        }

        private static void allCombinations(List<String>... lists) {
              allCombinations(lists, 1, "");
        }

        private static void allCombinations(List<String>[] lists, int index, String pre) {
            int nextHop = hop(index, lists.length-1);
          for (String s : lists[index]) {
            if (index != 0) {
              allCombinations(lists, nextHop, pre + s + "-");
            } else System.out.println(pre + s);
          }
        }
        private static int hop(int prevIndex, int maxResult){
            if (prevIndex%2 == 0){
                return prevIndex-2;
            } else {
                if (prevIndex == maxResult) 
                    return prevIndex-1;
                int nextHop = prevIndex+2;
                if (nextHop > maxResult){
                    return maxResult;
                } else return nextHop;
            }
        }

}

a "correct ordering" solution that allows lists of different sizes will have to start from the last list and work it's way backwards to the first list (lists[0]), appending the element at either beginning or end of the "pre" string and passing it onward. again, the first list will print the result. I'd have coded that, but lunch is ready and girlfriend is beginning to dislike stackoverflow...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文