我想对数组进行分区(例如[1,2,3,4,5,6,7,8]
),第一个分区应该保持偶数值,第二个奇数值(例如结果:[2,4,6,8,1,3,5,7]
)。
我设法使用内置Array.prototype
方法两次解决此问题。第一个解决方案使用map
和sort
,仅次于sort
。
我想制作第三种使用排序算法的解决方案,但我不知道用于分区列表的算法。我正在思考冒泡排序,但我认为它已用于我的第二个解决方案(array.sort((el1, el2)=>(el1 % 2 - el2 % 2))
)......我看了quicksort
,但我不知道在哪里申请检查整数是偶数还是奇数......
最好的(使用数组增长进行线性缩放)算法在保持元素顺序的情况下就地执行此类任务是什么?
答案 0 :(得分:2)
你可以很容易地在O(n)时间内就地做到这一点。在前面开始偶数索引,在后面开始奇数索引。然后,浏览数组,跳过第一个偶数块。
当您点击奇数时,从末尾向后移动以找到第一个偶数。然后交换偶数和奇数。
代码看起来像这样:
var i;
var odd = n-1;
for(i = 0; i < odd; i++)
{
if(arr[i] % 2 == 1)
{
// move the odd index backwards until you find the first even number.
while (odd > i && arr[odd] % 2 == 1)
{
odd--;
}
if (odd > i)
{
var temp = arr[i];
arr[i] = arr[odd];
arr[odd] = temp;
}
}
}
请原谅任何语法错误。 Javascript不是我的强项。
请注意,这不会保持相同的相对顺序。也就是说,如果你给它数组[1,2,7,3,6,8]
,那么结果将是[8,2,6,3,7,1]
。数组已分区,但奇数与原始数组的顺序不同。
答案 1 :(得分:0)
如果您坚持采用就地方法而不是简单的标准return [arr.filter(predicate), arr.filter(notPredicate)]
方法,那么可以使用两个索引轻松有效地实现这一点,从阵列的两侧运行并在必要时进行交换:
function partitionInplace(arr, predicate) {
var i=0, j=arr.length;
while (i<j) {
while (predicate(arr[i]) && ++i<j);
if (i==j) break;
while (i<--j && !predicate(arr[j]));
if (i==j) break;
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
return i; // the index of the first element not to fulfil the predicate
}
答案 2 :(得分:-1)
let evens = arr.filter(i=> i%2==0);
let odds = arr.filter(i=> i%2==1);
let result = evens.concat(odds);
我相信是O(n)。玩得开心。
编辑: 或者如果你真的关心效率:
let evens, odds = []
arr.forEach(i=> {
if(i%2==0) evens.push(i); else odds.push(i);
});
let result = evens.concat(odds);
答案 3 :(得分:-2)
Array.prototype.getEvenOdd= function (arr) {
var result = {even:[],odd:[]};
if(arr.length){
for(var i = 0; i < arr.length; i++){
if(arr[i] % 2 = 0)
result.odd.push(arr[i]);
else
result.even.push(arr[i]);
}
}
return result ;
};