Contains 3 options. Given an input array
- Unsorted and consecutive range, and array is 1 element short. eg: range is 6-9, and
array = [7, 8, 9]
output should be 6. - All conditions same as previous except 2 numbers are missing.
- Input is sorted, numbers are consecutive, array has one missing element.
Code:
final class Variables {
private final double x;
private final double y;
Variables(double x2, double y2) {
this.x = x2;
this.y = y2;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
@Override public String toString() {
return "x = " + x + " y = " + y;
}
}
public final class FindMissing {
private FindMissing() {};
/**
* The input array must contain only 1 element lesser than range.
* Returns a missing element.
*/
public static final int unsortedConsecutiveSingleMissing(int[] a1, int low, int high) {
// check that array length should be only 1 element less - can be avoided due to its mention in javadoc
if (a1 == null) throw new NullPointerException("a1 cannot be null. ");
if (low >= high) throw new IllegalArgumentException("The low: " + low + " should be lesser than high: " + high);
int total = (high * (high + 1)/2) - (low * (low + 1)/2) + low;
for (int i = 0; i < a1.length; i++) {
total = total - a1[i];
}
return total;
}
/**
* The input array must contain only 2 element lesser than range.
* Returns a missing element.
*
* Consecutive numbers are present, array is unsorted and a single number repeats.
*
* (a + b)2 = a2 + b2 + 2ab
*
* a + b = S' - S''
* a2 + b2 = T' - T''
*
* S' & S'' : sum of first and second sequence accordingly.
* T' & T'' : sum square of each number in T' and T'' accordingly.
*/
public static final Variables unsortedConsecutiveTwoMissing(int[] a1, int low, int high) {
if (a1 == null) throw new NullPointerException("a1 cannot be null. ");
if (low >= high) throw new IllegalArgumentException("The low: " + low + " should be lesser than high: " + high);
int sum1 = 0;
int squareSum1 = 0;
int x = low;
// careful. we need to be <= not <. due to muscle memory it is easy to be careless here.
while (x <= high) {
sum1 = sum1 + x;
squareSum1 = squareSum1 + x * x;
x++;
}
int sum2 = 0;
int squareSum2 = 0;
for (int i = 0; i < a1.length; i++) {
sum2 = sum2 + a1[i];
squareSum2 = squareSum2 + a1[i] * a1[i];
}
int sumDiff = sum1 - sum2;
int squareDiff = squareSum1 - squareSum2;
// (x + y)2 = x2 + y2 + 2xy
int product = ((sumDiff * sumDiff) - squareDiff) / 2;
return getVariables(product, sumDiff);
}
private static Variables getVariables(double product, double sum) {
// using reduced quadratic equation.
double x = (sum/2) - Math.sqrt( ((sum/2) * (sum/2)) - product);
double y = sum - x;
return new Variables(x, y);
}
/**
*
* The input array must be sorted and must contain only 1 element lesser than range.
* Returns a missing element.
*/
public static Integer sortedConsecutiveSingleMissing(int[] a1, int low) {
if (a1 == null) throw new NullPointerException("a1 cannot be null. ");
int start = a1[0];
if (start != low) {
return low;
}
int last = a1[a1.length - 1];
if (last != a1.length + low) {
return last + 1;
}
int lb = 0;
int hb = a1.length - 1;
while (lb <= hb) {
int mid = (lb + hb) / 2;
if (a1[mid] + 1 != a1[mid + 1]) {
return a1[mid] + 1;
}
if ((a1[mid] - mid) > start) {
hb = mid - 1;
} else {
lb = mid + 1;
}
}
return null;
}
}