Java 两个向量之间的置换

Java 两个向量之间的置换,java,algorithm,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 &l

我正在学习一些算法的技巧,但被一个问题绊住了,我需要在两组之间做一个排列。例如:

[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;
}
public void permutar(int[]num,int idx){
for(int i=idx;i

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

如对OP问题的评论中所述,您必须生成组合。通常的用例是从集合中获取一些元素子集。在这个问题中,您需要一个子集,它表示从第一个集合中获取的元素,其余的将从第二个集合中获取

为了实现这种组合,我建议循环计数从0到2^n(其中n是一个数组中的元素数)。然后取这个数字,用二进制表示。现在,二进制表示中的每个0或1表示应该从哪个集合中给定数字(第二个集合正好相反)


我猜这是一个家庭作业或心理练习,因此代码不包括在内:

您的任务等于列出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元素注释中的有序列表正确无误

显然,这些都是嵌套循环。

尽管您没有准确描述要查找的内容,并试图回答:看起来您只是在查找输入的所有3元素子集(1,2,3,5,6,7)。每个子集是一个解的第一个向量,其余元素是另一个向量

下面是一个基于我不久前编写的实用程序类的计算示例:

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]


计算不同的结果取决于您,但您可以相应地过滤结果)

您可以将其作为一个向量使用,或者将它们放入一个向量中,或者由一个getter根据数字选择向量1或向量2,然后进行置换。[1,2,3]e[5,6,7]和[1,2,3,5,6,7]的置换有什么区别。你不是简单地做了6个数字的排列吗?@flaschenpost有两个想法,一个想法:-)我不能像一个向量一样使用simple,因为我不想花费计算机处理来做1,2,3之间的排列,我只能在两个向量之间进行排列。[2,1,3]和[5,6,7]不是有效的置换。如果@Marco13是正确的,您可以使用位表示。i、 e.000是指
[1,2,3]e[5,6,7]
;101表示
[5,2,7]e[1,6,3]
。通过从
0
n
生成所有这些值,我不能这样做,因为一个数组中3个值的组合数不是2^3,而是更多。@NicolasBontempo:2^3没有那么大。所以,简单地列出这8个案例,告诉我们遗漏了什么。你说过[1,2,3]和[1,3,2]对你来说是相等的,所以实际上应该只有这8种情况。@flaschenpost抱歉,你是对的。只比2^3多1。[123][567][125][367][126][537][127][563][135][267][136][267][137][256][156][237][157][236][167][235]@NicolasBontempo你是对的,000-111是错的,所以Vaclav Blazej是错的。从定义运算的整个集合[1 2 3 5 6 7]中取6中的3。@flaschen是否用相等的解描述运算;)这将给我sets1[123][235][356][567]的答案,然后这将给我一个索引越界的错误。因为当i=5时,j等于6,k等于7(越界)。指数问题我有固定的对称解,避免了。但是,如果需要,您应该尝试查看嵌套循环。现在我得到了123125126127135136137156157167,所以4+3+2+1=10个解
[1, 2, 3] and [5, 6, 7]
[5, 6, 7] and [1, 2, 3]