分组数字JS算法

时间:2017-08-12 22:50:52

标签: javascript algorithm sorting

我试图解决问题:

问题:

  

给出一组正重复数字。产量   应该给出一个数组,其中赔率排在右边,而平均排在上面   离开(没有特别的顺序)

     

输入:[4,1,2,3,4]

     

输出:[4,2,3,1]

     

就地解决它而不使用额外的空间和O(N)运行时。

代码:

/*
 * Algorithm is simple, have two pointers one on the left and another on the right.
 * Note: We are sorting all evens on the left and odds on the right
 * If you see even on left, move on else swap.
 */

function groupNumbers(intArr) {

    if(intArr.length == 0 || intArr.length == 1){
        return intArr;
    }

    for(let i=0, j =intArr.length-1; i<intArr.length; i++){
        if(j>=i){ //elements should not overlap
            let start = intArr[i];
            let end = intArr[j];


            if(start%2 == 0){ //Even
                i++;
            } else {
                [start, end] = [end, start]; //swap
            }


            if(end%2 == 1){
                j--;
            } else {
                [start, end] = [end, start]; //swap
            }

        } //if-ends

    }//for-ends

    return intArr;
}

我不确定我哪里出错了。我错过了什么。我得到与输出相同的排序数组。

条件: **解决它INPLACE并且不使用额外空间**(最好在一次迭代中)

2 个答案:

答案 0 :(得分:1)

  

我不确定我哪里出错了。我错过了什么。我得到与输出相同的排序数组。

几件事:

let start = intArr[i];
let end = intArr[j];
...
[start, end] = [end, start];

这确实交换了变量startend中的值,而不是数组中的索引。

然后你在同一个循环中有两个i++来增加左指针。

if(start%2 == 0){ //Even
    i++;
} else {
    [start, end] = [end, start]; //swap
}

这里你在左指针指向奇数值时交换项目,但是没有检查右指针也指向偶数值。你不妨在这里交换两个奇数值。右指针也一样。

const isEven = v => (v&1) === 0;
const isOdd = v => (v&1) === 1;

function groupNumbers(arr){
  var left = 0, right = arr.length-1;
  while(left < right){
    //move the left pointer to find the next odd value on the left
    while(left < right && isEven(arr[left])) ++left;

    //move the right pointer to find the next even value on the right
    while(left < right && isOdd(arr[right])) --right; 

    //checking that the two pointer didn't pass each other
    if(left < right) {
      console.log("swapping %i and %i", arr[left], arr[right]);
      //at this point I know for sure that I have an odd value at the left pointer 
      //and an even value at the right pointer

      //swap the items
      var tmp = arr[left];
      arr[left] = arr[right];
      arr[right] = tmp;
    }
  }
  return arr;
}


[
  [1,2,3,4],
  [1,2,3,4,5,6,7,8,9,0],
  [1,3,5,7],
  [2,4,1,3],
  [5,4,3,2,1],
].forEach(sequence => {
  console.log("\ninput: " + sequence);
  console.log("output: " + groupNumbers(sequence));
});
.as-console-wrapper{top:0;max-height:100%!important}

正如@JaredSmith所建议的那样,只需使用排序函数:)

function sortEvenLeftOddRight(a,b){
  return (a&1) - (b&1);
  //return (a&1) - (b&1) || a-b;  //to additionally sort by value
}

[
  [1,2,3,4],
  [1,2,3,4,5,6,7,8,9,0],
  [1,3,5,7],
  [2,4,1,3],
  [5,4,3,2,1],
].forEach(sequence => {
  console.log("\ninput: " + sequence);
  sequence.sort(sortEvenLeftOddRight);
  console.log("output: " + sequence);
});
.as-console-wrapper{top:0;max-height:100%!important}

答案 1 :(得分:0)

解决此问题的一种非常简洁的方法是使用reduce

const out = arr.reduce((p, c) => {

  // if the value is divisible by 2 add it
  // to the start of the array, otherwise push it to the end
  c % 2 === 0 ? p.unshift(c) : p.push(c)
  return p;
}, []);

OUT

[4,2,4,1,3]

<强> DEMO