Reputation: 1163
I am attempting the Codility 'Leader' question in JavaScript.
The question is as follows:
An array
A
consisting ofN
integers is given. The dominator of arrayA
is the value that occurs in more than half of the elements ofA
.For example, consider array
A
such thatA[0] = 3 A[1] = 4 A[2] = 3 A[3] = 2 A[4] = 3 A[5] = -1 A[6] = 3 A[7] = 3
The dominator of
A
is 3 because it occurs in 5 out of 8 elements ofA
(namely in>
those with indices 0, 2, 4, 6 and 7) and 5 is more than a half of 8.Write a function
function solution(A);
that, given an arrayA
consisting ofN
integers, returns index of any element of arrayA
in which the dominator ofA
occurs. The function should return −1 if arrayA
does not have a dominator.For example, given array
A
such thatA[0] = 3 A[1] = 4 A[2] = 3 A[3] = 2 A[4] = 3 A[5] = -1 A[6] = 3 A[7] = 3
the function may return 0, 2, 4, 6 or 7, as explained above.
Write an efficient algorithm for the following assumptions:
N
is an integer within the range[0..100,000];
and each element of arrayA
is an integer within the range[−2,147,483,648..2,147,483,647]
.
My answer is below:
function solution(A) {
const length = A.length
if (length > 100000) return -1
const counters = new Array(length).fill(0)
const negativeCounters = new Array(length).fill(0)
for (i=0; i < length; i++){
if (A[i] < -2147483648 || A[i] > 2147483647) return -1
if (A[i] > -1){
counters[A[i]] = counters[A[i]] + 1
if (counters[A[i]] > (length / 2)) return i
} else {
negativeCounters[A[i] * -1] = negativeCounters[A[i] * -1] + 1
if (negativeCounters[A[i] * -1] > (length / 2)) return i
}
}
return -1
}
This is failing the correctness tests although I have tried a variety of inputs with which it succeeds. The Codility evaluation doesn't list the test input so I can't find input that is breaking the algorithm.
Can anyone spot the problem?
Upvotes: 1
Views: 3703
Reputation: 977
Swift 100% solution:
public func solution(_ A : inout [Int]) -> Int {
var result = 0
var stack = [Int]()
for element in A {
if stack.isEmpty || stack.last == element {
stack.append(element)
} else if stack.last != element {
stack.popLast()
}
}
guard let dominator = stack.last else { return -1 }
var count = 0
for i in 0..<A.count {
if dominator == A[i] {
count += 1
}
if count > A.count / 2 {
return i
}
}
return -1
}
Upvotes: 0
Reputation: 23955
Contrary to some comments and one answer, in fact using an array of counters in JavaScript works fine. This is because arrays in JavaScript are associative objects. One problem with your code is that it fails to initialise to zero counters whose key/index is greater than the initial counters array length.
Here is code that gets 100% on all of Codility's measures:
function solution(A) {
const arr = []
for (let i=0; i<A.length; i++){
if (!arr[A[i]])
arr[A[i]] = 1
else
arr[A[i]]++
if (arr[A[i]] > A.length/2)
return i
}
return -1
}
Upvotes: 3
Reputation: 8743
You shouldn't use an array with that big range of values (the array for the positive values would need a length of 2,147,483,648). You should use a map or in js you can use an object. I hacked something together, not very elegant, but it passes all tests:
function solution(A) {
const map = {}
for (let i = 0; i < A.length; i++) {
const key = '' + A[i]
map[key] = key in map ? map[key] + 1 : 1
if (map[key] > A.length / 2)
return i
}
return -1
}
Upvotes: 0