Counting Sort and Bucket Sort
Counting Sort:
Counting Sort is an efficient algorithm for sorting a collection of objects when the range of potential items is known and not too large.
Bucket Sort:
Bucket Sort improves upon simple algorithms like Counting Sort by distributing the elements among several "buckets" or lists, which are then sorted individually, typically using a different sorting algorithm.
1function countingSort(arr) {
2   let max = Math.max(...arr);
3   let count = Array(max+1).fill(0);
4   arr.forEach(item => count[item]++);
5   let output = []
6   for(let i = 0; i < count.length; i++) {
7    while(count[i] >0) {
8        output.push(i);
9        count[i]--
10    }
11   }
12   return output
13}
14
15
16let arr = [5, 2, 5, 5, 3, 1, 2, 5, 1, 5, 0, 5, 3, 1, 5, 2, 2, 2];
17console.log(countingSort(arr));
18
19//Buckert Sort is not good in cases where data is not uniform.
20//It's particularly useful when the input is uniformly distributed over a range.
21let arr = [11,9,21,8,17,19,13,1,24,12,21,22]
22function bucketSort(array, bucketSize = 5){
23    if (array.length === 0) {
24        return array;
25    }
26    let max = Math.max(...array)
27    let min = Math.min(...array)
28
29   
30   const bucketCount =  Math.floor((max - min)/bucketSize) + 1;
31
32const buckets = new Array(bucketCount);
33for (i = 0; i < buckets.length; i++) {
34    buckets[i] = [];
35}
36for(let i = 0; i < array.length; i++) {
37    buckets[Math.floor((array[i]-min)/bucketSize)].push(array[i]);
38}
39array.length = 0;
40for (i = 0; i < buckets.length; i++) {
41    buckets[i].sort((a, b) => a - b);
42    for (let j = 0; j < buckets[i].length; j++) {
43        array.push(buckets[i][j]);
44    }
45}
46return array;
47}
48
49let bucketSize = 5
50console.log(bucketSort(arr, bucketSize))
51
52
53//The space complexity is O(n+k)
54