计数排序

176 阅读1分钟

适合少量的非负数排序

思路

原数组值为下标,出现次数为值,生成新数组(a) 在将新数组(a)遍历,a下标为数组b的值,值为数b的push次数

「推导」

55124443
[_,1,1,1,3,2]
1,2,3push1次
4,push3次
5,push2次
[1,2,3,4,4,4,5,5]

「普通版」

function sortArray(nums: number[]): number[] {
  let len = nums.length;
  if (len === 1) {
    return nums;
  }
  //这是遍历原数组生成的count数组
  const count: (number | undefined)[] = [];

  for (let i = 0; i < len; i++) {
      //值作下标
    const j = nums[i];
    //判断该下标有没有值,如果有就++,没有就添加为1
    if (count[j]) {
    (count[j] as number)++;
    } else {
      count[j] = 1;
    }
  }
  const arr:number[] = []

  for(let i = 0;i<count.length;i++){
      //push次数
      let j = count[i]
      if(typeof j === 'number'){
        for(let k = 0;k<j;k++){
            arr.push(i)
        }
      }
  }
  return arr;
}

「优化版 支持负数」

//假设,原数组长度为100,值为10~90,那么10之前和90之后的全是undfined,由此新数组【count】长度为 max-min+1
//当有负数时min值就往左移长度不够就加,newmin和oldmin之间就可以放负数
//[负数,min,....]
function sortArray1(nums: number[]): number[] {
    let len = nums.length;
    if (len === 1) {
      return nums;
    }
    let min:number = nums[0]
    let max:number = nums[0]
    for(let i = 1;i<len;i++){
        if(nums[i] < min){
            min = nums[i]
        }
        if(nums[i] > max){
            max = nums[i]
        }
    }
    //这是遍历原数组生成的count数组
    const count: (number | undefined)[] = new Array(max-min+1);
    for (let i = 0; i < len; i++) {
        //值作下标
      const j = nums[i] - min;//相对下标
      //判断该下标有没有值,如果有就++,没有就添加为1
      if (count[j]) {
      (count[j] as number)++;
      } else {
        count[j] = 1;
      }
    }
    const arr:number[] = []
  
    for(let i = 0;i<count.length;i++){
        //push次数
        let j = count[i] 
        if(typeof j === 'number'){
          for(let k = 0;k<j;k++){
              arr.push(i+min)//真实下标
          }
        }
    }
    return arr;
  }

时间复杂度O(n+n+k) = O(n)

空间复杂度O(k)

未改变原先的顺序,稳定