我正在研究一些算法技术并陷入一个问题,我需要在两组之间进行排列。例如:
[1,2,3] e [5,6,7]
需要生成:
[5,2,3] e [1,6,7]
[5,6,3] e [1,2,7]
........
等等。
从到目前为止我所做的是在你自己之间的一个向量中进行排列。
传递一个向量[1,2,3]。产生答案: 123 132 213 231 321 312
基于以下代码:
public void permutar(int[] num, int idx) {
for (int i = idx; i < num.length; i++) {
swap(num, i, idx);
permutar(num, idx + 1);
swap(num, i, idx);
}
if (idx == num.length - 1) {
for (int i = 0; i < num.length; i++) {
System.out.print(num[i]);
}
System.out.println("");
}
}
public void swap(int[] num, int a, int b) {
int aux = num[a];
num[a] = num[b];
num[b] = aux;
}
如何在这两个向量之间进行排列?
答案 0 :(得分:2)
虽然你没有精确地描述你正在寻找的东西,并试图回答:看起来你只是在寻找输入的所有3元素子集(1,2,3, 5,6,7)。每个子集是一个解的第一个向量,相应的剩余元素是另一个向量。
以下是基于我前一段时间编写的ChoiceIterable实用程序类的计算方法示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
public class CombinationsOfVectors
{
public static void main(String[] args)
{
List<Integer> input = Arrays.asList(1,2,3,5,6,7);
ChoiceIterable<Integer> c = new ChoiceIterable<Integer>(3, input);
for (List<Integer> v0 : c)
{
Set<Integer> s = new LinkedHashSet<Integer>(input);
s.removeAll(v0);
List<Integer> v1 = new ArrayList<Integer>(s);
System.out.println(v0+" and "+v1);
}
}
}
// From https://github.com/javagl/Combinatorics/blob/master/src/
// main/java/de/javagl/utils/math/combinatorics/ChoiceIterable.java
// See the GitHub repo for a commented version
class ChoiceIterable<T> implements Iterable<List<T>>
{
private final List<T> input;
private final int sampleSize;
private final long numElements;
public ChoiceIterable(int sampleSize, List<T> input)
{
this.sampleSize = sampleSize;
this.input = input;
long nf = factorial(input.size());
long kf = factorial(sampleSize);
long nmkf = factorial(input.size() - sampleSize);
long divisor = kf * nmkf;
long result = nf / divisor;
numElements = result;
}
private static long factorial(int n)
{
long f = 1;
for (long i = 2; i <= n; i++)
{
f = f * i;
}
return f;
}
@Override
public Iterator<List<T>> iterator()
{
return new Iterator<List<T>>()
{
private int current = 0;
private final int chosen[] = new int[sampleSize];
{
for (int i = 0; i < sampleSize; i++)
{
chosen[i] = i;
}
}
@Override
public boolean hasNext()
{
return current < numElements;
}
@Override
public List<T> next()
{
if (!hasNext())
{
throw new NoSuchElementException("No more elements");
}
List<T> result = new ArrayList<T>(sampleSize);
for (int i = 0; i < sampleSize; i++)
{
result.add(input.get(chosen[i]));
}
current++;
if (current < numElements)
{
increase(sampleSize - 1, input.size() - 1);
}
return result;
}
private void increase(int n, int max)
{
if (chosen[n] < max)
{
chosen[n]++;
for (int i = n + 1; i < sampleSize; i++)
{
chosen[i] = chosen[i - 1] + 1;
}
}
else
{
increase(n - 1, max - 1);
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException(
"May not remove elements from a choice");
}
};
}
}
此示例中的输出将为
[1, 2, 3] and [5, 6, 7]
[1, 2, 5] and [3, 6, 7]
[1, 2, 6] and [3, 5, 7]
[1, 2, 7] and [3, 5, 6]
[1, 3, 5] and [2, 6, 7]
[1, 3, 6] and [2, 5, 7]
[1, 3, 7] and [2, 5, 6]
[1, 5, 6] and [2, 3, 7]
[1, 5, 7] and [2, 3, 6]
[1, 6, 7] and [2, 3, 5]
[2, 3, 5] and [1, 6, 7]
[2, 3, 6] and [1, 5, 7]
[2, 3, 7] and [1, 5, 6]
[2, 5, 6] and [1, 3, 7]
[2, 5, 7] and [1, 3, 6]
[2, 6, 7] and [1, 3, 5]
[3, 5, 6] and [1, 2, 7]
[3, 5, 7] and [1, 2, 6]
[3, 6, 7] and [1, 2, 5]
[5, 6, 7] and [1, 2, 3]
如果这不是您一直在寻找的,那么您应该更清楚,更准确地描述预期结果。
(例如,是否
[1, 2, 3] and [5, 6, 7]
和
[5, 6, 7] and [1, 2, 3]
计算不同的结果取决于您,但您可以相应地过滤结果)
答案 1 :(得分:0)
如对OP问题的评论中所述,您必须生成组合。通常的用例是从集合中获取一些元素子集。在这个问题中,您将获取表示从第一组中获取的元素的子集,其余的将从第二组中获取。
为了实现组合,我建议从0到2 ^ n的for循环计数(其中n是一个数组中的元素数)。然后取这个数字并用二进制表示。现在每个0或1的二进制表示都说明应从哪个集合给出数字(第二个集合将完全相反)。
我猜你有这个作为家庭作业或心理练习所以代码不包括在内:]
答案 2 :(得分:0)
您的任务等于列出6个元素集的所有3元素子集。由于3元素集内的顺序无关紧要,因此您应该定义一个顺序,例如“较小的数字首先出现”。
然后算法变得明显:list = [1 2 3 5 6 7]
编辑:Set1应该始终是数字1的集合,以避免对称相同的解决方案。
对于所有数字我从2到5 对于从i + 1到5的所有数字j Set1 = {list [1],list [i],list [j]} Set2 =“其他数字”
这应该从你的9个元素的评论中给出你的有序列表。
显然这些是嵌套循环。