How to sort an array efficiently

半城伤御伤魂 提交于 2021-02-05 11:28:27

问题


I'm trying to sort an array [3,3,2,1,3,2,2,2,1] to [1,1,3,3,3,2,2,2,2].

I'm trying to handle it using object, using the number as key, and the occurrence as value.

const sortNums = (arr) => {
  const result = {}

  for (let i = 0; i < arr.length; i++) {
    const num = result[arr[i]] || 0;
    result[arr[i]] = num + 1;
  }
  //The above will gives me { '1': 2, '2': 4, '3': 3 }

  //How to convert back to array?
}

console.log(sortNums([3,3,2,1,3,2,2,2,1]))

Of course I can use the Object.entries to map back to an array, but then the entire algorithm will be consider O(n^2) right? I'm trying to explore if it can be achieve in O(n) instead. Or I shouldn't use object to begin with?


回答1:


You could get the count for sorting the array.

const sortNums = array => {
    const count = {};
    for (let v of array) count[v] = (count[v] || 0) + 1;
    return array.sort((a, b) => count[a] - count[b] || a - b);
}

console.log(sortNums([3, 3, 2, 1, 3, 2, 1]));

An approach by using the object for sorting.

const sortNums = array => {
    var count = {},
        result = {};
    for (let v of array) (count[v] = count[v] || []).push(v);
    for (let a of Object.values(count)) (result[a.length] = result[a.length] || []).push(a);
    return Object.values(result).flat(Infinity)
}

console.log(sortNums([3, 3, 2, 1, 3, 2, 1]));



回答2:


You can do this

const sortNums = (arr) => {
    const result = {}

    for (let i = 0; i < arr.length; i++) {
      const num = result[arr[i]] || 0;
      result[arr[i]] = num + 1;
    }

    const a = [];
    for(let i = 0; i <= 9; i++) {
        if(result[i]) {
            a.push(...Array.from({length: result[i]}, x => i));
        }
    }
    return a;
  }



回答3:


Try something like

var curIndex = 0;
for i in result {
   arr.fill(i, curIndex, curIndex + result[i]);
   curIndex = curIndex + result[i];
}



回答4:


Assuming that the numbers are small non-negative integers, you can count them as you have done already, and then generate the result on the fly when someone (Array.from() in this example) requests for it, with a simple pair of loops:

function *sortNums(array){
  let stats=[];
  for(var i of array)
    stats[i]=(stats[i]||0)+1;

  for(let i=0;i<stats.length;i++)
    while(stats[i]>0){
      stats[i]--;
      yield i;
    }
}

console.log(Array.from(sortNums([3, 3, 10, 2, 1, 0, 3, 2, 1])).join());

Of course it is possible to just collect the pieces into an array, in the direct, "traditional" way:

let ret=[];
for(let i=0;i<stats.length;i++)
  while(stats[i]>0){
    stats[i]--;
    ret.push(i);//yield i;
  }
return ret;


来源:https://stackoverflow.com/questions/58730313/how-to-sort-an-array-efficiently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!