package com.freetymekiyan.algorithms.level.medium; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number and every other * number afterward until you reach the end of the list. * <p> * Repeat the previous step again, but this time from right to left, remove the right most number and every other number * from the remaining numbers. * <p> * We keep repeating the steps again, alternating left to right and right to left, until a single number remains. * <p> * Find the last number that remains starting with a list of length n. * <p> * Example: * <p> * Input: * n = 9, * 1 2 3 4 5 6 7 8 9 * 2 4 6 8 * 2 6 * 6 * <p> * Output: * 6 */ public class EliminationGame { private EliminationGame eg; /** * Calculate the start point of next round with: * The start point of this round, the step, the number of removed integers. * If from left, start = start + step * len - step / 2 * If from right, start = start - step * len + step / 2 * step / 2 is actually the step of last round. * Stop when only one integer remain. */ public int lastRemaining(int n) { int start = 1; int step = 2; int len = n; boolean isFromLeft = true; while (len != 1) { len >>= 1; if (isFromLeft) { start = start + step * len - step / 2; } else { start = start - step * len + step / 2; } step <<= 1; isFromLeft = !isFromLeft; } return start; } @Before public void setUp() { eg = new EliminationGame(); } @Test public void testExamples() { Assert.assertEquals(1, eg.lastRemaining(1)); Assert.assertEquals(2, eg.lastRemaining(2)); Assert.assertEquals(2, eg.lastRemaining(3)); Assert.assertEquals(2, eg.lastRemaining(4)); Assert.assertEquals(2, eg.lastRemaining(5)); Assert.assertEquals(4, eg.lastRemaining(6)); Assert.assertEquals(4, eg.lastRemaining(7)); Assert.assertEquals(6, eg.lastRemaining(8)); Assert.assertEquals(6, eg.lastRemaining(9)); Assert.assertEquals(8, eg.lastRemaining(10)); Assert.assertEquals(8, eg.lastRemaining(11)); } @After public void tearDown() { eg = null; } }