Java solution to Codility Dominator problem (Lesson 8 – Leader) which scored 100%. The problem is to find the value that occurs in more than half of the elements of a given integer array.
The strategy is:
- use a java.util.Stack and push duplicate values onto the stack to find a dominator candidate
- if encounter a number that doesn’t exist on top of stack, pop the stack
- if the stack is not empty after going through all the array elements, then we have a candidate (not necessarily a dominator)
- go through array again to see if the dominator value occurrs more than n/2 times
[cc lang="java" escaped="true"] package com.codility.lesson08.leader; import java.util.Stack; public class Dominator { public int solution(int[] A) { Stack stack = new Stack(); for(int i=0; i<A.length; i++) { if(stack.isEmpty()) { stack.push(A[i]); } else { if(stack.peek().intValue() == A[i]) { stack.push(A[i]); } else { stack.pop(); } } } //no candidate if stack is empty if(stack.isEmpty()) return -1; int candidate = stack.peek().intValue(); int count = 0; int candidateIndex = -1; for(int i=0; i<A.length; i++) { if(A[i] == candidate) { count++; if(candidateIndex < 0) { candidateIndex = i; //only store index of first occurence of candidate } } } //works for even and odd number of A elements //e.g. if A.length = 4, count needs to be > 2 //e.g. if A.length = 5, count needs to be > 2 if(count > (A.length / 2)) return candidateIndex; return -1; //no dominator found } } [/cc]
TestNG test cases for this problem which all passed:
[cc lang="java" escaped="true"] package test.com.codility.lesson08.leader; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.codility.lesson08.leader.Dominator; public class DominatorTests { private Dominator solution; @BeforeTest public void setUp() { solution = new Dominator(); } @DataProvider(name = "test1") public Object [][] createData1() { return new Object [][] { new Object [] { new int [] { 3, 4, 3, 2, 3, -1, 3, 3 }, 0 }, new Object [] { new int [] { 100, 100, 100, 100, 100, 100 }, 0 }, new Object [] { new int [] { 100, -1000, 100, -1000, -1000 }, 1 }, new Object [] { new int [] { 1, 2, 3 }, -1 }, new Object [] { new int [] { 1000000000 }, 0 }, new Object [] { new int [] { 1000, 1 }, -1 }, new Object [] { new int [] { 0, 0 }, 0 }, }; } @Test(dataProvider = "test1") public void verifySolution(int [] pA, int pExpected) { Assert.assertEquals(solution.solution(pA), pExpected); } } [/cc]