我有一个包含32个数字的数组[1,2,3,4,4,4,4,5,5,5,5,5,6,6,7,7,7,7,8,9,10,10,11,12,13,13,14,14,15,16,17,17]
我想把这个数组分成8个大小为4的子数组,以便没有子数组具有重复元素。
我可以用多少种方式做到这一点?生成所有排列和单个随机排列的最优解是什么。子数组的顺序不重要。每个子数组内部元素的顺序也不重要。
对于我的原始问题,我不需要生成所有排列。我只需要在每次运行程序时生成一个随机排列。
我的方法是使用Fisher–Yates算法随机洗牌数组,并继续重新洗牌,直到我得到8个没有重复元素的子数组。当然这不是最好的方法。
作为解决方案的一部分,我会打乱数组并从这个打乱的数组中开始逐个添加元素到子数组中。如果任何子数组已经有了一个数字,那么我就跳过来自我的打乱数组的元素,直到我到达子数组中不存在的数字。这种方法在某些情况下失败。
我尝试的伪代码
let shuffledArray = shuffle(originalArray);
let subArrays = [];
for (let i = 0; i < 8; i++) {
subArrays[i] = [];
for (let j = 0; j < 32; j++) {
if (!subArrays[i].contains(shuffledArray[j]) && !shuffledArray[j].used) {
subArrays[i].push(shuffledArray[j])
shuffledArray[j].used = true;
}
if (subArrays[i].length == 4) {
break;
}
}
}
if subArrays has any sub array such that it has duplicate elements then repeat above steps
else we have generated a random permutation
如您所见,当重复的数字都在末尾时,上述方法会失败,因此我将一遍又一遍地重复所有步骤直到得到结果。
我正在使用JavaScript,但只要能转换成JavaScript,任何语言的答案都可以。
如果有人能为N个元素和K个组提供通用解决方案,那就太好了。
这是我在SO上的第一个问题。随意编辑/建议改进。
[1,2,3,4][4,5,6,7][4,5,6,7][4,5,7,8][5,7,9,10][5,10,11,12][13,14,15,17][13,14,16,17]
和[1,2,13,14][4,5,16,17][4,5,6,7][4,5,7,8][5,7,9,10][5,10,11,12][13,14,15,17][3,4,6,7]
和[17,2,13,4][4,5,6,7][4,5,6,7][4,5,7,8][5,7,9,10][5,10,11,12][13,14,15,17][3,14,16,1]
。 - Faizan