求教,这个问题怎么实现。

通过一个输入框,输入一个自定义的数组,例如1,4,5,23,2,17,24,10000000。请把他按照中间高两边低进行排序,最后的结果是1,4,5,23,10000000,24,17,2,算法越准确越好,请注意左右翼数据数据的平衡性

阅读 2.4k
6 个回答

先排序,从高到低。再循环,根据下标index + 1判断奇偶来执行push或unshift

排序之后,不断的取数,往一个新数组或左,或是右塞数字

const arr = [1, 4, 5, 23, 2, 17, 24, 10000000];

function getArr(arr) {

 return arr.sort((a, b) => b - a).reduce((a, b, index) => {

 index % 2 ? a.push(b) : a.unshift(b);

 return a;

 }, [])

}

console.log(getArr(arr));

先对数组正常排序,然后遍历排序好的数组, 数组索引除2取商和模. 模为0,则商为该索引值在新数组里的索引;模为1,则数组长度减商再减1为该索引值再新数组里的索引

排序后,先移出最大的数字,然后其它的数字先想加求出总和除2,的到两边想加的最优解,然后从大往小加,只要大于和大于最优解之后,计算大于最优解多少,然后刚才的和再减去最后加的一个数字,来看下小于最优解多少,比较绝对值,就知道最后加的那个数字放到哪边差值小了,然后再把刚才的数组倒序一下,加上最大的值就可以了..

这个遇到一些奇葩的数组,好像也不是最优的.
[1,2,3,4,5,7,100,6,16] 像这个,,上面的方法计算的,肯定是 [1,2,3,4,5,6,100,7,16]

所以,理论上来说,从大往小,找到一组的和 去除最大值然后除2的到的商最接近即可. 然后最小的数字在的数组正排序,另外一个数组到排序,中间加上最大值即可

[1,2,3,4,5,6,100,99]
[1,2,3,4,5,6,100,9,13]

function uDontKnowExactlyWhatUWant_And_IsThisANPCompleteProblem(input) {
  let minDiff = Infinity;
  function tryToFind(
    arr,
    n,
    elems,
    soln,
    sum,
    numSelected = 0,
    currSum = 0,
    position = 0
  ) {
    if (position === n) return;
    if (((n / 2) | 0) - numSelected > n - position) return;
    tryToFind(arr, n, elems, soln, sum, numSelected, currSum, position + 1);
    numSelected++;
    currSum = currSum + arr[position];
    elems[position] = true;
    if (numSelected === ((n / 2) | 0)) {
      const diff = Math.abs(((sum / 2) | 0) - currSum);
      if (diff < minDiff) {
        minDiff = diff;
        for (let i = 0; i < n; i++) soln[i] = elems[i];
      }
    } else {
      tryToFind(arr, n, elems, soln, sum, numSelected, currSum, position + 1);
    }
    elems[position] = false;
  }

  const arr = input.sort((a, b) => (a > b ? 1 : -1));
  const maxnum = arr.pop();
  let curr_elements = [];
  let soln = [];
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
    curr_elements[i] = soln[i] = false;
  }

  tryToFind(arr, arr.length, curr_elements, soln, sum, 0, 0, 0);
  const left = [];
  const right = [];
  input.forEach((n, i) => (soln[i] ? right : left).push(n));
  left.push(maxnum);
  right.sort((a, b) => (a < b ? 1 : -1));
  return [].concat(left, right);
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8];
const a = uDontKnowExactlyWhatUWant_And_IsThisANPCompleteProblem(arr);
console.log(a); //  [1, 2, 4, 7, 8, 6, 5, 3]

排序,算平均数,遍历时累加,正序塞进数组,当 sum >= average * length / 2 时,改成逆序塞,没了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题