package me.ramswaroop.arrays; import java.util.Arrays; /** * Created by IntelliJ IDEA. * * @author: ramswaroop * @date: 8/17/15 * @time: 7:23 PM */ public class TwoRepeatingElements { /** * Finds the 2 repeating elements in an array {@param a} of 1 to n elements and n+2 length. This is * similar to {@link me.ramswaroop.bits.TwoNonRepeatingElements}. * <p/> * EXPLANATION: * Let the repeating numbers be X and Y, if we xor all the elements in the array and all integers from 1 to n, * then the result is X xor Y. * The 1’s in binary representation of X xor Y is corresponding to the different bits between X and Y. * Suppose that the kth bit of X xor Y is 1, we can xor all the elements in the array and all integers * from 1 to n, whose kth bits are 1. The result will be one of X and Y. * * @param a * @return */ public static int[] getTwoRepeatingElements(int[] a) { int xor = a[0]; int rightMostSetBit; int x = 0, y = 0; for (int i = 1; i < a.length; i++) { xor ^= a[i]; } for (int i = 1; i <= a.length - 2; i++) { xor ^= i; } // now xor is X xor Y, therefore find any of its set bit rightMostSetBit = xor & ~(xor - 1); for (int i = 0; i < a.length; i++) { // one number will have a set bit at that position and other wouldn't if ((a[i] & rightMostSetBit) == 0) { x ^= a[i]; } else { y ^= a[i]; } } for (int i = 1; i <= a.length - 2; i++) { // one number will have a set bit at that position and other wouldn't if ((i & rightMostSetBit) == 0) { x ^= i; } else { y ^= i; } } return new int[]{x, y}; } /** * The algorithm is simple. We use index of the array to track repeating elements. * Once we encounter a element lets say 2 then we make the element in 2nd index -ve just * to mark that we have encountered 2. When we encounter 2 again and see that 2nd index * is already -ve we conclude that 2 is repeated. * * Similar to {@link me.ramswaroop.arrays.DuplicatesInArray#findDuplicatesInArray(int[])}. * * @param a * @return */ public static int[] findTwoRepeatingElements(int[] a) { int[] repeatingElements = new int[2]; for (int i = 0, j = 0; i < a.length; i++) { if (a[Math.abs(a[i])] >= 0) { a[Math.abs(a[i])] = -a[Math.abs(a[i])]; } else { repeatingElements[j++] = Math.abs(a[i]); } } return repeatingElements; } public static void main(String a[]) { System.out.println(Arrays.toString(getTwoRepeatingElements(new int[]{4, 2, 4, 5, 2, 3, 1}))); System.out.println(Arrays.toString(getTwoRepeatingElements(new int[]{2, 4, 5, 2, 3, 1, 6, 7, 7}))); System.out.println(Arrays.toString(getTwoRepeatingElements(new int[]{1, 2, 1, 2}))); System.out.println("========"); System.out.println(Arrays.toString(findTwoRepeatingElements(new int[]{4, 2, 4, 5, 2, 3, 1}))); System.out.println(Arrays.toString(findTwoRepeatingElements(new int[]{2, 4, 5, 2, 3, 1, 6, 7, 7}))); System.out.println(Arrays.toString(findTwoRepeatingElements(new int[]{1, 2, 1, 2}))); } }