0

The Counting Sort 1 challenge from HackerRank is as follows:

Challenge:

Given a list of integers, count and return the number of times each value appears as an array of integers.

Function Description:

Complete the countingSort function in the editor below.

countingSort has the following parameter(s):

arr[n]: an array of integers

Returns:

int[100]: a frequency array

Input Format:

The first line contains an integer n, the number of items in arr. Each of the next n lines contains an integer arr[i] where 0 <= i < n.

My code:

function countingSort(arr) {
    // Write your code here
    let freqArray = [];
    let frequency = 0;
    
    for(let i=0; i <= arr.length; i++){
        if(i != 0){
            freqArray.push(frequency);
        }
        frequency = 0;
        for(let j=0; j <= arr.length; j++){
            if(arr[i] == arr[j]){
                frequency++;
            }
        }
    }
    
    return freqArray;
}

Input:

63 25 73 1 98 73 56 84 86 57 16 83 8 25 81 56 9 53 98 67 99 12 83 89 80 91 39 86 76 85 74 39 25 90 59 10 94 32 44 3 89 30 27 79 46 96 27 32 18 21 92 69 81 40 40 34 68 78 24 87 42 69 23 41 78 22 6 90 99 89 50 30 20 1 43 3 70 95 33 46 44 9 69 48 33 60 65 16 82 67 61 32 21 79 75 75 13 87 70 33

My output:

1 3 2 2 2 2 2 1 2 1 2 2 1 3 2 2 2 1 2 2 2 1 2 3 1 1 2 2 1 1 1 2 3 2 1 1 1 3 2 2 3 2 2 2 2 1 2 3 1 2 1 3 2 2 2 1 1 2 1 2 1 3 1 1 2 1 1 2 2 3 1 2 1 2 1 2 2 1 3 2 2 2 3 1 3 1 1 2 1 2 1 3 2 2 2 2 1 2 2 3

Expected output:

0 2 0 2 0 0 1 0 1 2 1 0 1 1 0 0 2 0 1 0 1 2 1 1 1 3 0 2 0 0 2 0 3 3 1 0 0 0 0 2 2 1 1 1 2 0 2 0 1 0 1 0 0 1 0 0 2 1 0 1 1 1 0 1 0 1 0 2 1 3 2 0 0 2 1 2 1 0 2 2 1 2 1 2 1 1 2 2 0 3 2 1 1 0 1 1 1 0 2 2

Maybe I just don't understand how frequency works, but if I look arr[2] = 73 and arr[5] = 73, i conclude 73 appears 2 times in this array, hence my output. However the expected output is 0. Can someone explain to me what I am missing?

  • The output is supposed to be an array that maps the index into the array to a frequency count. So `frequency[0]` should represent how many times 0 appears in the input array, `frequency[1]` how many times 1 appears, and so on. – Pointy Mar 12 '23 at 16:38
  • You do not need nested loops. All you need to do is iterate through the input array and increment the value in the output array for each value. – Pointy Mar 12 '23 at 16:38
  • Right. What YOUR output says is "the item in spot 0 (that is, 63) appears once, the item in spot 1 (25) appears 3 times". That's not the assignment. In the expected output, the count for the value 63 appears in the 63rd entry. – Tim Roberts Mar 12 '23 at 18:30

1 Answers1

0

Each index in return array should represent the number of which you count the occurrence frequency, maybe shorter data input would help you, lets imagine short input array: [2, 3, 2], the correct result would be: [0, 0, 2, 1], you could translate this result to speech like: number 0 occurred 0 times, number 1 occurred 0 times, number 2 occurred 2 times, number 3 occurred 1 time.

If i modify your code to working condition its like this (please note this is not the best way to this):

function countingSort(arr) {
    // create array of length maximum number + 1 (+ 1 because of indexing from 0)
    // and fill whole array with zeros, to have the default state
    let freqArray = new Array(Math.max(...arr)+1).fill(0);
    
    // you had error here "less or equal"
    // value of arr.length is 100, but arr[100] is not defined
    // array indexing start at 0 which takes place, so last item is at arr[99]
    for(let i=0; i < arr.length; i++){
        // just for convenience
        let number = arr[i];
        // skip if we already calculated the occurrence of this number
        if(freqArray[number] != 0) continue;
        // the current number is counted as 1 in following statement
        let frequency = 1;
        // all previous numbers was already counted no need to do it again
        // that is why we start at i+1
        for(let j=i+1; j < arr.length; j++){
            if(number == arr[j]){
                frequency++;
            }
        }
        // we got the frequency lets save it to the result array
        freqArray[number] = frequency;
    }
    
    return freqArray;
}

So that was the nested loop approach, while it works its slow because each array item is compared toward every other item in array, which is expensive, time complexity is O(n log n), you could do the same thing at time complexity O(n) so its more simple and straight forward, hidden so you can figure it out yourself:

function countingSort(arr) {
    let freqArray = new Array(Math.max(...arr)+1).fill(0);
    
    for(let i = 0; i < arr.length; i++){
            freqArray[arr[i]]++;
    }
    
    return freqArray;
}
Kazz
  • 1,030
  • 8
  • 16