如何在 JavaScript 中实现蝴蝶洗牌算法?
在 JavaScript 中,蝴蝶洗牌数组是指一个数字数组,其排序方式为:越靠近数组中心,数字越小;越靠近数组两端,数字越大。最大的数字位于第一个索引位置。
蝴蝶洗牌数组的另一种变体是:越靠近数组中心,数字越大;越靠近数组两端,数字越小。在这种情况下,最小的数字位于第一个索引位置。
对于有数学背景的人来说,这与高斯分布有些相似。
示例
假设我们有以下数组:
const arr = [8,2,6,3,9,1,4,5,0,7];
如果我们对其应用蝴蝶洗牌算法,输出将为:
[9, 7, 5, 3, 1,0, 2, 4, 6, 8]
可以看到,最大和第二大的数字位于数组的两端,最小的数字位于数组的中心。
另一种可能性是:
[0, 2, 4, 6, 8, 9, 7, 5, 3, 1]
我们的任务是编写一个函数,该函数接收一个数字数组和一个字符串作为第二个参数,字符串可以取两个值中的任何一个:“asc” 或 “des”。
如果字符串为“des”,则我们必须按升序到降序的顺序对数组进行洗牌。
如果字符串为“asc”,则我们必须按降序到升序的顺序对数组进行洗牌。
方法
如果字符串为“asc”,我们首先按升序对数组进行排序,否则按降序排序。因此,假设函数被调用时带了“asc”,那么数组现在将如下所示:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
然后我们将数组分成两个数组,使相邻元素分布在不同的数组中。我们将元素推入一个数组,同时将其移到另一个数组的开头,这样一来,一个数组就会被反转,而无需我们手动进行反转操作。
这样形成的两个数组将如下所示:
[ 0, 2, 4, 6, 8 ] [ 9, 7, 5, 3, 1 ]
现在,最后一步是连接这两个数组,之后我们将得到所需的数组。将所有这些代码放在一起,看起来就像这样:
示例
const array = [8,2,6,3,9,1,4,5,0,7]; const butterflyShuffle = (array, order = 'asc') => { //creating a new copy of array so that we dont mutate the original array const arr = array.slice(); //sorting ascending or descending based on the argument arr.sort((a, b) => order === 'asc' ? a-b : b-a); const first = [], second = []; //this variable will later help in determining which array is to be reversed //and which one is to be concatenated to which //if length is even, it means that last element will go in second array //otherwise it will go in first array const isEven = arr.length % 2 === 0; for (let i = 0; i < arr.length; i++){ if(i % 2 === 0){ isEven ? first.push(arr[i]) : first.unshift(arr[i]); continue; }; isEven ? second.unshift(arr[i]) : second.push(arr[i]); }; return isEven ? second.concat(first) : first.concat(second); }; console.log(butterflyShuffle(array)); console.log(butterflyShuffle(array, 'des'));
输出
控制台中的输出将为:
[ 9, 7, 5, 3, 1, 0, 2, 4, 6, 8 ] [ 0, 2, 4, 6, 8, 9, 7, 5, 3, 1 ]
广告