'MaxCounters (lesson 4 in codility) - 100% correctness but 60% on efficiency, why?
Link to the problem in a nutshell: N is an integer that represent number of counters and the max counter allowed. A is an array that represent the operation done on specific counter(for example if A[0] is 1, and N is 3 we need to add 1 to 'counters' array[0]) if element in A is N+1, all element in counter should be change to the largest number in the counter array. I submitted the code I wrote and got only 60% in performance, why is that? any way I should aproach a problem next time to make it more efficient? how can I improve?
function solution(N,A){
let counters = Array(N).fill(0);
let maxCounter = 0;
for(i=0;i<A.length;i++){
if(A[i]<=N){
counters[A[i]-1]++
if(counters[A[i]-1]>maxCounter){maxCounter = counters[A[i]-1]};
}
else if(A[i]===N+1){
counters = Array(N).fill(maxCounter)
}
}
return counters
}
Edit: I didn't know that this website wasn't meant for question regarding code improvement, thanks, I will ask somewhere else.
Solution 1:[1]
One possible improvement would be, when you need to fill the whole array with the new max counters, don't create an entirely new array to do so - instead, change the existing array.
else if(A[i]===N+1){
counters.fill(maxCounter)
}
This could have a large effect if there are a whole lot of counters.
Solution 2:[2]
Here is a solution using object which will generate the actual array only once (after all operations are applied).
The "tracker" object will only ever hold the indices & values of those counters which have an operation. Say, N (ie, "num" number of counters) is 50,000 but only 5,000 counters have an explicit operation in A (ie, "arr" array), only those 5,000 elements will be tracked (using the "tracker" object).
Code Snippet
// alternative solution using object
const counterOps = (num, arr) => {
// the "tracker" object we will use to populate the result array
const tracker = {};
// when "num+1" to reset all elements to "max", then
// the "max" value is stored in "lastMaxSet"
let lastMaxSet = 0;
// helper method to get current max from "tracker"
const getMax = obj => Math.max(...Object.values(obj));
// helper method to "set" "all" values to "max"
const setMax = obj => {
lastMaxSet = getMax(obj);
Object.keys(obj).forEach(k => obj[k] = lastMaxSet);
};
// iterate through "arr" and "apply" each "operation"
arr.forEach(elt => {
if (elt === num + 1) {
// "reset to max" operation is applied
setMax(tracker);
} else {
// a particular counter is incremented
const k = elt - 1;
tracker[k] ??= lastMaxSet;
tracker[k]++;
}
});
// the "tracker" object is used to generate
// the result-array on-the-fly
return [...Array(num).fill(lastMaxSet)].map(
(val, idx) => idx in tracker ? tracker[idx] : val
);
};
console.log(counterOps(5, [3, 4, 4, 6, 1, 4, 4]));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Please try out and share feedback if it helped at all (with performance).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | CertainPerformance |
| Solution 2 | jsN00b |
