Dominator – Codility – Solution

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]