两个向量之间的排列

时间:2015-08-29 22:21:58

标签: java algorithm

我正在研究一些算法技术并陷入一个问题,我需要在两组之间进行排列。例如:

[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;
}

如何在这两个向量之间进行排列?

3 个答案:

答案 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个元素的评论中给出你的有序列表。

显然这些是嵌套循环。