Algorithm 如何从可变长度的数组中找到由1个元素组成的所有置换?

Algorithm 如何从可变长度的数组中找到由1个元素组成的所有置换?,algorithm,permutation,Algorithm,Permutation,我有一个数组U,数组D的长度不同。我需要能够返回数组索引的所有排列,这些排列将从每个集合中选择由1个元素组成的不同排列。我还要求将此算法表示为一个只记住最后一个置换的对象,并使用get_next方法返回下一个置换 例如,U=[大小为n1的数组,大小为n2的数组,大小为n3的数组]会有n1*n2*n3的排列,每3个元素长 编辑:集合的数量也不同。所以。。。这不是很简单吗 你需要一个迭代器。您希望它迭代最后一个数组。当它到达该数组的末尾时,增加它在最后一个数组中的当前位置,并返回到最后一个数组的开头

我有一个数组U,数组D的长度不同。我需要能够返回数组索引的所有排列,这些排列将从每个集合中选择由1个元素组成的不同排列。我还要求将此算法表示为一个只记住最后一个置换的对象,并使用get_next方法返回下一个置换

例如,U=[大小为n1的数组,大小为n2的数组,大小为n3的数组]会有n1*n2*n3的排列,每3个元素长

编辑:集合的数量也不同。

所以。。。这不是很简单吗

你需要一个迭代器。您希望它迭代最后一个数组。当它到达该数组的末尾时,增加它在最后一个数组中的当前位置,并返回到最后一个数组的开头

使用Cs返回语法的psuedocode:

编辑:如果集合的数量不同,可以使用某种形式的递归:

function next(list)
    firstArray = list.first
    iterator = iterator(list.rest)
    if !iterator
        foreach i in firstArray
            yield return i
    else
        foreach i in firstArray
            while (iterator.hasNext)
                yield return (i, iterator.next)

考虑一个长度为1的列表时的行为,然后考虑长度为2的列表的行为,并让自己确信它实际上是在工作的。

< P>你可以在每个数组中保持一个计数器来确定你的个人位置。在get_下一个方法中,增加1的计数器,并根据数组的长度对其进行修改。然后,只要在前一个计数器滚动到0时增加下一个计数器

if (pos3 == array_of_size_n3 -1)
{
   if (pos2 == size_of_array_2 -1)
   {
       pos1 = (pos1 + 1) % size_of_array_1

   }
   pos2 = (pos2 + 1) % size_of_array_2
}
pos3 = (pos3 + 1) % size_of_array_3

print array1[pos1], array2[pos2], array3[pos3]

编辑:如果数组的数量不同,请将位置变量保留在一个数组中。事实上,这可能会更好。通过这种方式,您可以像引用数组本身一样引用pos变量。

要理解Anon所说的内容,您不需要在它们上面循环。在类中维护状态,以便知道每个数组的最后一个索引是什么。逻辑是一样的,但是你不能在一个连续的循环中运行。伪代码逻辑为:

get_next() { oldn3 = this.n3; oldn2 = this.n2; oldn1 = this.n1; if(this.n3 == this.a3.Count) this.n3 = 0; else this.n3++; if(oldn3 > this.n3) if(this.n2 == this.a2.Count) this.n2 = 0; else this.n2++; if(oldn2 > this.n2) if(this.n1 == this.a1.Count) this.n1 = 0; else this.n1++; if(oldn1 > this.n1) return NO_MORE_PERMS; return [n1,n2,n3]; } getCurrent() { return [n1,n2,n3]; }
如果您使用的是python,这是标准库的一部分:itertools.product。但假设你不是,这里有一个伪代码版本

// Create an initialised array of indexes.
int[] index0(arrays) {
    // We require all arrays to be non-empty.
    for a in arrays {
        assert len(a) != 0;
    }
    return new int[len(arrays)];
}

// Increment the indices. Returns false when the indices wrap round to the start.
bool next_index(indices, arrays) {
    for (i = len(indices) - 1; i >= 0; --i) {
        indices[i] += 1
        if indices[i] < len(arrays[i]) {
            return true;
        }
        indices[i] = 0;
    }
    return false;
}
假设所有数组都不为空,则可以这样使用它。本例打印出数组中元素的每个组合

indices = index0(arrays); 
{
    for (i = 0; i < len(arrays); ++i) {
        print arrays[i][indices[i]];
    }
    print
} while next_index(indices);

哎呀,我忘了提到有一个变量的数量sets@James在这条线路的某个地方,你将不得不为自己做一些腿部工作。虽然Anon没有指出集合的数量是可变的,但这是你应该能够自己解决的问题,因为其他人会给你剩余的。虽然公平地说,基于嵌套循环的解决方案实现可变数量的集合通常是不平凡的。要使这项工作适用于任意长度的数组,将n1、n2、n3等存储在阵列中。对该数组进行索引,以便索引i是集合i的当前元素;此外,还要注意边界检查。在一个基于0的系统上,我上面所说的将不起作用。漂亮而简洁!我的排名比我的好。你用错了术语。正确的术语是笛卡尔积@詹姆斯-集合的数量在长度上也有变化,这是没有意义的。集合的数量是一个数字。没有长度,谢谢你,先生。我认为这个词可能已经存在了,但如果你只需要继续它所描述的现象,就很难找到它。
indices = index0(arrays); 
{
    for (i = 0; i < len(arrays); ++i) {
        print arrays[i][indices[i]];
    }
    print
} while next_index(indices);