Looking through different combinations through matrix using just visited int variable? - java

I am looking at this topcoder problem here:
http://community.topcoder.com/tc?module=ProblemDetail&rd=4725&pm=2288
Under the java section there is this code :
public class KiloManX {
boolean ddd = false;
int[] s2ia(String s) {
int[] r = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
r[i] = s.charAt(i) - '0' ;
}
return r;
}
public int leastShots(String[] damageChart, int[] bossHealth) {
int i, j, k;
int n = damageChart.length;
int[][] dc = new int[n][];
int[] cost = new int[1 << n];
for (i = 0; i < n; i++) {
dc[i] = s2ia(damageChart[i]) ;
}
for (i = 1; i < 1 << n; i++) {
cost[i] = 65536 * 30000;
for (j = 0; j < n; j++) {
int pre = i - (1 << j);
if ((i & (1 << j)) != 0) {
cost[i] = Math.min(cost[i], cost[pre] + bossHealth[j]) ;
for (k = 0; k < n; k++) {
if ((i & (1 << k)) != 0 && k != j && dc[k][j] > 0) {
cost[i] = Math.min(cost[i],
cost[pre] + (bossHealth[j] + dc[k][j] - 1) / dc[k][j]);
}
}
}
}
}
return cost[(1 << n) - 1] ;
}
static void pp(Object o) {
System.out.println(o);
}
}
I am trying to understand what he is been done. So what I understand is :
i - keeps track of the visited nodes somehow(this is the most baffling part of the code)
j - is the monster we want to defeat
k - is the previous monster's weapon we are using to defeat j
dc is the input array of string into a matrix
cost, keep cost at each step, some sort of dynamic programming? I don't understand how cost[1 << n] can give the result?
What I understand is they are going through all the possible sets / combinations. What I am baffled by (even after executing and starring at this for more than a week) is:
how do they keep track of all the combinations?
I understand pre - is the cost of the previous monster defeated (i.e. how much cost we incurred there), but I don't understand how you get it from just (i - 1 << j).
I have executed the program(debugger), stared at it for more than a week, and tried to decode it, but I am baffled by the bit-manipulation part of the code. Can someone please shed light on this?

cost, keep cost at each step, some sort of dynamic programming?
They are partial costs, yes, but characterizing them as per-step costs misses the most important significance of the indices into this array. More below.
I don't understand how cost[1 << n] can give the result?
That doesn't give any result by itself, of course. It just declares an array with 2n elements.
how do they keep track of all the combinations?
See below. This is closely related to why the cost array is declared the size it is.
I understand pre - is the cost of the previous monster defeated (i.e. how much cost we incurred there), but I don't understand how you get it from just (i - 1 << j).
Surely pre is not itself a cost. It is, however, used conditionally as an index into the cost array. Now consider the condition:
if ((i & (1 << j)) != 0) {
The expression i & (1 << j) tests whether bit j of the value of i is set. When it is, i - (1 << j) (i.e. pre) evaluates to the the result of turning off bit j of the value of i. That should clue you in that the indices of cost are bit masks. The size of that array (1 << n) is another clue: it is the number of distinct n-bit bitmasks.
The trick here is a relatively common one, and a good one to know. Suppose you have a set of N objects, and you want somehow to represent all of its subsets (== all the distinct combinations of its elements). Each subset is characterized by whether each of the N objects is an element or not. You can represent that as N numbers, each either 0 or 1 -- i.e. N bits. Now suppose you string those bits together into N-bit numbers. Every integer from 0 (inclusive) to 2N (exclusive) has a distinct pattern of its least-significant N bits, so each corresponds to different subset.
The code presented uses exactly this sort of correspondence to encode the different subsets of the set of bosses as different indices into the cost array -- which answers your other question of how it keeps track of combinations. Given one such index i that represents a subset containing boss j, the index i - (1 << j) represents the set obtained from it by removing boss j.
Roughly speaking, then, the program proceeds by optimizing the cost of each non-empty subset by checking all the ways to form it from a subset with one element fewer. (1 << n) - 1 is the index corresponding to the whole set, so at the end, that element of cost contains the overall optimized value.

Related

Find the minimal absolute value of a sum of two elements

I am solving the Codility problem provided below,
Let A be a non-empty array consisting of N integers.
The abs sum of two for a pair of indices (P, Q) is the absolute value |A[P] + A[Q]|, for 0 ≤ P ≤ Q < N.
For example, the following array A:
A[0] = 1 A1 = 4 A[2] = -3 has pairs of indices (0, 0), (0,
1), (0, 2), (1, 1), (1, 2), (2, 2). The abs sum of two for the pair
(0, 0) is A[0] + A[0] = |1 + 1| = 2. The abs sum of two for the pair
(0, 1) is A[0] + A1 = |1 + 4| = 5. The abs sum of two for the pair
(0, 2) is A[0] + A[2] = |1 + (−3)| = 2. The abs sum of two for the
pair (1, 1) is A1 + A1 = |4 + 4| = 8. The abs sum of two for the
pair (1, 2) is A1 + A[2] = |4 + (−3)| = 1. The abs sum of two for
the pair (2, 2) is A[2] + A[2] = |(−3) + (−3)| = 6.`
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty array A consisting of N integers, returns the minimal abs sum of two for any pair of indices in this array.
For example, given the following array A:
A[0] = 1 A1 = 4 A[2] = -3 the function should return 1, as
explained above.
Given array A:
A[0] = -8 A1 = 4 A[2] = 5 A[3] =-10 A[4] = 3 the function
should return |(−8) + 5| = 3.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000]; each element of array A is an integer within the range [−1,000,000,000..1,000,000,000].
I write the solution provided below.
public static int solution(int[] A) {
int N = A.length;
Arrays.sort(A);
if (A[0] >= 0) {
return 2 * A[0];
}
int i = 0;
int j = N - 1;
int sum = Math.abs((A[i] + A[j]));
// -10, -8, 3, 4, 5
while (i <= j) {
if (Math.abs(A[i + 1] + A[j]) < sum) {
++i;
sum = Math.abs(A[i] + A[j]);
} else if (Math.abs(A[i] + A[j - 1]) < sum) {
--j;
sum = Math.abs(A[i] + A[j]);
} else {
i++;
j--;
}
}
return sum;
}
The solution gets hanged in the online judge and seems it enters in a forever loop. Is there a possibility that the code can enter a non-ending loop?
UPDATE
After I update the solution with the all negatives check, the code passed the online judge and provides a good performance.
if(A[N-1] <=0){
return 2* Math.abs(A[N-1]);
}
For input arrays e.g({-1, -2, -3}, {-1, -2}, {-1} your algorithm throws ArrayIndexOutOfBoundsException, so arrays when there are only negative numbers and there is no repeats
There is no chance to reach endless loop because either i or j change only + or - 1
I would like to explain the algorithm that I have implemented and then the implementation in C++.
Sort the array because otherwise we would need to check any two arbitrary indices. That brute-force solution would result in O(N ^ 2) runtime complexity.
We initialise the min abs sum to something higher than the possible value in the arrays.
Apply the caterpillar method by having front and back indices.
In every iteration, update the min abs sum as and when needed.
There two special cases:
a. all values are zero or positive. We could return A[front] * 2 early.
b. all values are negative or zero. We could return A[back] * 2 early.
In both cases, we could return early, however, it would result in a bit more code, so I personally avoid that. In the above cases, we can still go through the array without degrading the overall runtime complexity. In these cases, it also does not matter how we go through the array with regards to the result, so I just go through the array in one way in both cases. But the code will be shared with the third case.
In the third case, where the array, and thereby the sorted array, contains both negative and positive values, we try to keep the sum of front and back to zero since this when the abs sum value is minimised. In other words, we try to keep the balance between the negative and positive numbers by keeping their distance to the minimum.
Therefore, if the sum of front and back are less than zero, then we know that the negative front value is greater than the positive back value. As a direct consequence of that, we need to advance the front index.
If the sum of front and back are equal to zero, then we found the smallest min abs sum that is ever possible. The absolute value cannot be less than zero. Whilst I could return at this point in the code for some constant optimisation, I do not do so to keep the code the minimal and also functional.
If the sum of front and back are greater than zero, then we know that the negative front value is less than the positive back value. As a direct consequence of that, we need to decrease the index.
We loop until the front and back indices meet, but we handle the case when they are equal since according to the task specification, the same index can be used twice for the absolute sum.
The runtime complexity of this solution is O(N * logN) because the sorting of the array is O(N * logN) and the loop is O(N) since we go through every element. Therefore, the sorting runtime complexity dominates the loop.
The space complexity is O(1) because we only allocate constant space independently from the number of inputs. The sorting is done in place.
int solution(vector<int> &A)
{
const int N = A.size();
sort(A.begin(), A.end());
int min_abs_sum_of_two = INT_MAX;
for (int front = 0, back = N - 1; front <= back;) {
const int ef = A[front];
const int eb = A[back];
min_abs_sum_of_two = min(min_abs_sum_of_two, abs(ef + eb));
if (ef + eb < 0) ++front; else --back;
}
return min_abs_sum_of_two;
}
I got 100% for following code ( java). Slightly modified version of https://www.techiedelight.com/find-pair-array-minimum-absolute-sum/
import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// sort the array if it is unsorted
Arrays.sort(A);
int low = 0;
int high = A.length - 1;
if (A[0] >= 0) {
return 2 * A[0];
}
if (A[high] <= 0) {
return -2 * A[high];
}
// maintain two indexes pointing to endpoints of the array
// `min` stores the minimum absolute difference
int min = Integer.MAX_VALUE;
int i = 0, j = 0;
// reduce the search space `A[low…high]` at each iteration of the loop
int sum = 0;
// loop if `low` is less than `high`
while (low < high)
{
// update the minimum if the current absolute sum is less.
sum = A[high] + A[low];
if (Math.abs(sum) < min)
{
min = Math.abs(sum);
i = low;
j = high;
}
// optimization: pair with zero-sum is found
if (min == 0) {
break;
}
// increment `low` index if the total is less than 0;
// decrement `high` index if the total is more than 0
if (sum < 0) {
low++;
}
else {
high--;
}
}
return min;
}
}
The Answer is late but I hope to help anyone have the same question
//============================================================================
// Author: Hamdy Abd El Fattah
// Code is like humor. When you have to explain it, it’s bad.
//============================================================================
#include <bits/stdc++.h>
#define FIO cin.tie(0), cin.sync_with_stdio(0)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int main() {
FIO;
ll n , m = INF , x;
vector<ll> positive,negative;
cin>>n;
while(n--){
cin>>x;
if(x < 0)
negative.push_back(x * -1);
else if(x > 0)
positive.push_back(x);
else
m = 0;
}
if(m == 0){
cout<<"0\n";
}else{
sort(positive.begin(), positive.end());
sort(negative.begin(), negative.end());
int i= 0, j = 0;
int positive_size = positive.size(), negative_size =negative.size();
while(i < positive_size || j < negative_size){
if(abs(positive[i] - negative[j]) < m){
m=abs(positive[i] - negative[j]);
m=min(min(m,positive[i]*2),negative[j] * 2);
}
if((i < positive_size && positive[i] <= negative[j]) || j == negative_size)
i++;
else if((j < negative_size && positive[i] > negative[j]) || i == positive_size)
j++;
}
cout<<m<<endl;
}
return 0;
}

Cumulative bitwise operations

Suppose you have an Array A = [x, y, z, ...]
And then you compute a prefix/cumulative BITWISE-OR array P = [x, x | y, x | y | z, ... ]
If I want to find the BITWISE-OR of the elements between index 1 and index 6, how can I do that using this precomputed P array? Is it possible?
I know it works in cumulative sums for getting sum in a range, but I am not sure with bit operations.
Edit: duplicates ARE allowed in A, so A = [1, 1, 2, 2, 2, 2, 3] is a possibility.
There is impossible to use prefix/cumulative BITWISE-OR array to calculate the Bitwise-or of some random range, you can try with a simple case of 2 elements and verify yourself.
However, there is different approach, which is making use of prefix sum.
Assuming that we are dealing with 32 bit integer, we know that, for the bitwise-or sum from range x to y, the ith bit of the result will be 1 if there exists a number in range (x,y) that has ith bit is 1. So by answering this query repeatedly:
Is there any number in range (x, y) that has ith bit set to 1?
We can form the answer to the question.
So how to check that in range (x, y), there is at least a number that has bit ith set? we can preprocess and populate the array pre[n][32]which contain the prefix sum of all 32 bit within the array.
for(int i = 0; i < n; i++){
for(int j = 0; j < 32; j++){
//check if bit i is set for arr[i]
if((arr[i] && (1 << j)) != 0){
pre[i][j] = 1;
}
if( i > 0) {
pre[i][j] += pre[i - 1][j];
}
}
}
And, to check if bit i is set form range (x, y) is equalled to check if:
pre[y][i] - pre[x - 1][i] > 0
Repeat this check 32 times to calculate the final result:
int result = 0;
for (int i = 0; i < 32; i++){
if((pre[y][i] - (i > 0 ? pre[x - 1][i] : 0)) > 0){
result |= (1 << i);
}
}
return result;
A plain prefix array does not work, because in order to support arbitrary range queries it requires elements to have an inverse relative to the operator, so for example for addition that inverse is negation, for XOR that inverse is the element itself, for bitwise OR there is no inverse.
A binary indexed tree also does not work, for the same reason.
But a sideways heap does work, at the cost of storing about 2*n to 4*n elements (depending on how much is added by rounding up to a power of two), a much smaller expansion than 32*n. This won't make the most exciting use of a sideways heap, but it avoids the problems of an explicitly linked tree: chunky node objects (~32 bytes per node) and pointer chasing. A regular implicit binary tree could be used, but that makes it harder to relate its indexes to indexes in the original array. A sideways heap is like a full binary tree but, notionally, with no root - effectively we do have a root here, namely the single node on the highest level that is stored. Like a regular implicit binary tree a sideways heap is implicitly linked, but the rules are different:
left(x) = x - ((x & -x) >> 1)
right(x) = x + ((x & -x) >> 1)
parent(x) = (x & (x - 1)) | ((x & -x) << 1)
Additionally we can compute some other things, such as:
leftmostLeaf(x) = x - (x & -x) + 1
rightmostLeaf(x) = x + (x & -x) - 1
The lowest common ancestor of two nodes, but the formula is a bit large.
Where x & -x can be written as Integer.lowestOneBit(x).
The arithmetic looks obscure, but the result is a structure like this, which you can step through the arithmetic to confirm (source: The Art of Computer Programming volume 4A, bitwise tricks and techniques):
Anyway we can use this structure in the following way:
store the original elements in the leaves (odd indexes)
for every even index, store the bitwise OR of its children
for a range query, compute the OR of elements that represent a range that does not go outside the queried range
For the query, first map the indexes to leaf indexes. For example 1->3 and 3->7. Then, find the lowest common ancestor of the endpoints (or just start at the highest node) and recursively define:
rangeOR(i, begin, end):
if leftmostLeaf(i) >= begin and rightmostLeaf(i) <= end
return data[i]
L = 0
R = 0
if rightmostLeaf(left(i)) >= begin
L = rangeOR(left(i), begin, end)
if leftmostLeaf(right(i)) <= end
R = rangeOR(right(i), begin, end)
return L | R
So any node that corresponds to a range that is totally covered is used as a whole. Otherwise, if the left or right children are covered at all they must be recursively queried for their contribution, if either of them is not covered then just take zero for that contribution. I am assuming, by the way, that the query is inclusive on both ends, so the range includes both begin and end.
It turns out that rightmostLeaf(left(i)) and leftmostLeaf(right(i)) can be simplified quite a lot, namely to i - (~i & 1) (alternative: (i + 1 & -2) - 1) and i | 1 respectively. This seems awfully asymmetrical though. Under the assumption that i is not a leaf (it won't be in this algorithm, since a leaf is either fully covered or not queried at all), they become i - 1 and i + 1 respectively, much better. Anyway we can use that all the left descendants of a node have a lower index than it, and all right descendants have a higher index.
Written out in Java it could be (not tested):
int[] data;
public int rangeOR(int begin, int end) {
return rangeOR(data.length >> 1, 2 * begin + 1, 2 * end + 1);
}
private int rangeOR(int i, int begin, int end) {
// if this node is fully covered by [begin .. end], return its value
int leftmostLeaf = i - (i & -i) + 1;
int rightmostLeaf = i + (i & -i) - 1;
if (leftmostLeaf >= begin && rightmostLeaf <= end)
return data[i];
int L = 0, R = 0;
// if the left subtree contains the begin, query it
if (begin < i)
L = rangeOR(i - (Integer.lowestOneBit(i) >> 1), begin, end);
// if the right subtree contains the end, query it
if (end > i)
R = rangeOR(i + (Integer.lowestOneBit(i) >> 1), begin, end);
return L | R;
}
An alternative strategy is starting from the bottom and going up until the two sides meet, while collecting data on the way up. When starting at begin and its parent is to the right of it, the right child of the parent has a higher index than begin so it is part of the queried range - unless the parent was the common ancestor of both upwards "chains". For example (not tested):
public int rangeOR(int begin, int end) {
int i = begin * 2 + 1;
int j = end * 2 + 1;
int total = data[i];
// this condition is only to handle the case that begin == end,
// otherwise the loop exit is the `break`
while (i != j) {
int x = (i & (i - 1)) | (Integer.lowestOneBit(i) << 1);
int y = (j & (j - 1)) | (Integer.lowestOneBit(j) << 1);
// found the common ancestor, so done
if (x == y) break;
// if the low chain took a right turn, the right child is part of the range
if (i < x)
total |= data[x + (Integer.lowestOneBit(x) >> 1)];
// if the high chain took a left turn, the left child is part of the range
if (j > y)
total |= data[y - (Integer.lowestOneBit(y) >> 1)];
i = x;
j = y;
}
return total;
}
Building the tree in the first place is not trivial, building it in ascending order of indexes does not work. It can be built level-by-level, starting at the bottom. Higher nodes are touched early (for example for the first layer the pattern is 2, 4, 6, while 4 is in the second layer), but they will be overwritten anyway, it's fine to temporarily leave a non-final value there.
public BitwiseORRangeTree(int[] input) {
// round length up to a power of two, then double it
int len = input.length - 1;
len |= len >> 1;
len |= len >> 2;
len |= len >> 4;
len |= len >> 8;
len |= len >> 16;
len = (len + 1) * 2;
this.data = new int[len];
// copy input data to leafs, odd indexes
for (int i = 0; i < input.length; i++)
this.data[i * 2 + 1] = input[i];
// build higher levels of the tree, level by level
for (int step = 2; step < len; step *= 2) {
for (int i = step; i < this.data.length; i += step) {
this.data[i] = this.data[i - (step >> 1)] | this.data[i + (step >> 1)];
}
}
}

How to calculate number of swaps in permutations?

I have this code below, I would like to know how to calculate the number of swaps. I used a count variable to figure it out, but I was getting different number than the computer. I figure the number of swaps would be 2 * (n - 1)(n - 2)...(n - n + 1). For n == 4, the computer got 128, and I got 48. What am I doing wrong?
public void permute(int n) {
if (n == 1) {
printOutPut();
}
for (int i = 1; i <= n; i++){
swap(i, n);
permute1(n-1);
swap(i, n);
}
}
The code defines a recursion:
num_swaps(0) = 0
num_swaps(i) = i * (num_swaps(i - 1) + 2)
or with more math-like symbols:
s_{n+1} = (n + 1) (s_n + 2)
s_0 = 0
s_1 = 2
s_2 = 8
s_3 = 30
s_4 = 128
You can probably solve that recursion for a general n using techniques from maths, but this verifies that the computer is right
Edit: I was trying to find a solution for general n, ended up on wolfram alpha and the solution presented had incomplete gamma functions and stuff. So, don't expect the calculation to be easy!

represent an integer using binary in java language

Here is the problem:
You're given 2 32-bit numbers, N & M, and two bit positions, i & j. write a method to set all bits between i and j in N equal to M (e.g. M becomes a substring of N at locating at i
and starting at j)
For example:
input:
int N = 10000000000, M = 10101, i = 2, j = 6;
output:
int N = 10001010100
My solution:
step 1: compose one mask to clear sets from i to j in N
mask= ( ( ( ((1<<(31-j))-1) << (j-i+1) ) + 1 ) << i ) - 1
for the example, we have
mask= 11...10000011
step 2:
(N & mask) | (M<<i)
Question:
what is the convenient data type to implement the algorithm? for example
we have int n = 0x100000 in C, so that we can apply bitwise operators on n.
in Java, we have BitSet class, it has clear, set method, but doesnt support
left/right shift operator; if we use int, it supports left/right shift, but
doesnt have binary representation (I am not talking about binary string representation)
what is the best way to implement this?
Code in java (after reading all comments):
int x = Integer.parseInt("10000000000",2);
int x = Integer.parseInt("10101",2);
int i = 2, j = 6;
public static int F(int x, int y, int i, int j){
int mask = (-1<<(j+1)) | (-1>>>(32-i));
return (mask & x ) | (y<<i);
}
the bit-wise operators |, &, ^ and ~ and the hex literal (0x1010) are all available in java
32 bit numbers are ints if that constraint remains int will be a valid data type
btw
mask = (-1<<j)|(-1>>>(32-i));
is a slightly clearer construction of the mask
Java's int has all the operations you need. I did not totally understand your question (too tired now), so I'll not give you a complete answer, just some hints. (I'll revise it later, if needed.)
Here are j ones in a row: (1 << j)-1.
Here are j ones in a row, followed by i zeros: ((1 << j) - 1) << i.
Here is a bitmask which masks out j positions in the middle of x: x & ~(((1 << j) - 1) << i).
Try these with Integer.toBinaryString() to see the results. (They might also give strange results for negative or too big values.)
I think you're misunderstanding how Java works. All values are represented as 'a series of bits' under the hood, ints and longs are included in that.
Based on your question, a rough solution is:
public static int applyBits(int N, int M, int i, int j) {
M = M << i; // Will truncate left-most bits if too big
// Assuming j > i
for(int loopVar = i; loopVar < j; loopVar++) {
int bitToApply = 1 << loopVar;
// Set the bit in N to 0
N = N & ~bitToApply;
// Apply the bit if M has it set.
N = (M & bitToApply) | N;
}
return N;
}
My assumptions are:
i is the right-most (least-significant) bit that is being set in N.
M's right-most bit maps to N's ith bit from the right.
That premature optimization is the root of all evil - this is O(j-i). If you used a complicated mask like you did in the question you can do it in O(1), but it won't be as readable, and readable code is 97% of the time more important than efficient code.

Quickest way to find missing number in an array of numbers

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
I have an array of numbers from 1 to 100 (both inclusive). The size of the array is 100. The numbers are randomly added to the array, but there is one random empty slot in the array.
What is the quickest way to find that slot as well as the number that should be put in the slot? A Java solution is preferable.
You can do this in O(n). Iterate through the array and compute the sum of all numbers. Now, sum of natural numbers from 1 to N, can be expressed as Nx(N+1)/2. In your case N=100.
Subtract the sum of the array from Nx(N+1)/2, where N=100.
That is the missing number. The empty slot can be detected during the iteration in which the sum is computed.
// will be the sum of the numbers in the array.
int sum = 0;
int idx = -1;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == 0)
{
idx = i;
}
else
{
sum += arr[i];
}
}
// the total sum of numbers between 1 and arr.length.
int total = (arr.length + 1) * arr.length / 2;
System.out.println("missing number is: " + (total - sum) + " at index " + idx);
We can use XOR operation which is safer than summation because in programming languages if the given input is large it may overflow and may give wrong answer.
Before going to the solution, know that A xor A = 0. So if we XOR two identical numbers the value is 0.
Now, XORing [1..n] with the elements present in the array cancels the identical numbers. So at the end we will get the missing number.
// Assuming that the array contains 99 distinct integers between 1..99
// and empty slot value is zero
int XOR = 0;
for(int i=0; i<100; i++) {
if (ARRAY[i] != 0) // remove this condition keeping the body if no zero slot
XOR ^= ARRAY[i];
XOR ^= (i + 1);
}
return XOR;
//return XOR ^ ARRAY.length + 1; if your array doesn't have empty zero slot.
Let the given array be A with length N. Lets assume in the given array, the single empty slot is filled with 0.
We can find the solution for this problem using many methods including algorithm used in Counting sort. But, in terms of efficient time and space usage, we have two algorithms. One uses mainly summation, subtraction and multiplication. Another uses XOR. Mathematically both methods work fine. But programatically, we need to assess all the algorithms with main measures like
Limitations(like input values are large(A[1...N]) and/or number of
input values is large(N))
Number of condition checks involved
Number and type of mathematical operations involved
etc. This is because of the limitations in time and/or hardware(Hardware resource limitation) and/or software(Operating System limitation, Programming language limitation, etc), etc. Lets list and assess the pros and cons of each one of them.
Algorithm 1 :
In algorithm 1, we have 3 implementations.
Calculate the total sum of all the numbers(this includes the unknown missing number) by using the mathematical formula(1+2+3+...+N=(N(N+1))/2). Here, N=100. Calculate the total sum of all the given numbers. Subtract the second result from the first result will give the missing number.
Missing Number = (N(N+1))/2) - (A[1]+A[2]+...+A[100])
Calculate the total sum of all the numbers(this includes the unknown missing number) by using the mathematical formula(1+2+3+...+N=(N(N+1))/2). Here, N=100. From that result, subtract each given number gives the missing number.
Missing Number = (N(N+1))/2)-A[1]-A[2]-...-A[100]
(Note:Even though the second implementation's formula is derived from first, from the mathematical point of view both are same. But from programming point of view both are different because the first formula is more prone to bit overflow than the second one(if the given numbers are large enough). Even though addition is faster than subtraction, the second implementation reduces the chance of bit overflow caused by addition of large values(Its not completely eliminated, because there is still very small chance since (N+1) is there in the formula). But both are equally prone to bit overflow by multiplication. The limitation is both implementations give correct result only if N(N+1)<=MAXIMUM_NUMBER_VALUE. For the first implementation, the additional limitation is it give correct result only if Sum of all given numbers<=MAXIMUM_NUMBER_VALUE.)
Calculate the total sum of all the numbers(this includes the unknown missing number) and subtract each given number in the same loop in parallel. This eliminates the risk of bit overflow by multiplication but prone to bit overflow by addition and subtraction.
//ALGORITHM
missingNumber = 0;
foreach(index from 1 to N)
{
missingNumber = missingNumber + index;
//Since, the empty slot is filled with 0,
//this extra condition which is executed for N times is not required.
//But for the sake of understanding of algorithm purpose lets put it.
if (inputArray[index] != 0)
missingNumber = missingNumber - inputArray[index];
}
In a programming language(like C, C++, Java, etc), if the number of bits representing a integer data type is limited, then all the above implementations are prone to bit overflow because of summation, subtraction and multiplication, resulting in wrong result in case of large input values(A[1...N]) and/or large number of input values(N).
Algorithm 2 :
We can use the property of XOR to get solution for this problem without worrying about the problem of bit overflow. And also XOR is both safer and faster than summation. We know the property of XOR that XOR of two same numbers is equal to 0(A XOR A = 0). If we calculate the XOR of all the numbers from 1 to N(this includes the unknown missing number) and then with that result, XOR all the given numbers, the common numbers get canceled out(since A XOR A=0) and in the end we get the missing number. If we don't have bit overflow problem, we can use both summation and XOR based algorithms to get the solution. But, the algorithm which uses XOR is both safer and faster than the algorithm which uses summation, subtraction and multiplication. And we can avoid the additional worries caused by summation, subtraction and multiplication.
In all the implementations of algorithm 1, we can use XOR instead of addition and subtraction.
Lets assume, XOR(1...N) = XOR of all numbers from 1 to N
Implementation 1 => Missing Number = XOR(1...N) XOR (A[1] XOR A[2] XOR...XOR A[100])
Implementation 2 => Missing Number = XOR(1...N) XOR A[1] XOR A[2] XOR...XOR A[100]
Implementation 3 =>
//ALGORITHM
missingNumber = 0;
foreach(index from 1 to N)
{
missingNumber = missingNumber XOR index;
//Since, the empty slot is filled with 0,
//this extra condition which is executed for N times is not required.
//But for the sake of understanding of algorithm purpose lets put it.
if (inputArray[index] != 0)
missingNumber = missingNumber XOR inputArray[index];
}
All three implementations of algorithm 2 will work fine(from programatical point of view also). One optimization is, similar to
1+2+....+N = (N(N+1))/2
We have,
1 XOR 2 XOR .... XOR N = {N if REMAINDER(N/4)=0, 1 if REMAINDER(N/4)=1, N+1 if REMAINDER(N/4)=2, 0 if REMAINDER(N/4)=3}
We can prove this by mathematical induction. So, instead of calculating the value of XOR(1...N) by XOR all the numbers from 1 to N, we can use this formula to reduce the number of XOR operations.
Also, calculating XOR(1...N) using above formula has two implementations. Implementation wise, calculating
// Thanks to https://a3nm.net/blog/xor.html for this implementation
xor = (n>>1)&1 ^ (((n&1)>0)?1:n)
is faster than calculating
xor = (n % 4 == 0) ? n : (n % 4 == 1) ? 1 : (n % 4 == 2) ? n + 1 : 0;
So, the optimized Java code is,
long n = 100;
long a[] = new long[n];
//XOR of all numbers from 1 to n
// n%4 == 0 ---> n
// n%4 == 1 ---> 1
// n%4 == 2 ---> n + 1
// n%4 == 3 ---> 0
//Slower way of implementing the formula
// long xor = (n % 4 == 0) ? n : (n % 4 == 1) ? 1 : (n % 4 == 2) ? n + 1 : 0;
//Faster way of implementing the formula
// long xor = (n>>1)&1 ^ (((n&1)>0)?1:n);
long xor = (n>>1)&1 ^ (((n&1)>0)?1:n);
for (long i = 0; i < n; i++)
{
xor = xor ^ a[i];
}
//Missing number
System.out.println(xor);
This was an Amazon interview question and was originally answered here: We have numbers from 1 to 52 that are put into a 51 number array, what's the best way to find out which number is missing?
It was answered, as below:
1) Calculate the sum of all numbers stored in the array of size 51.
2) Subtract the sum from (52 * 53)/2 ---- Formula : n * (n + 1) / 2.
It was also blogged here: Software Job - Interview Question
Here is a simple program to find the missing numbers in an integer array
ArrayList<Integer> arr = new ArrayList<Integer>();
int a[] = { 1,3,4,5,6,7,10 };
int j = a[0];
for (int i=0;i<a.length;i++)
{
if (j==a[i])
{
j++;
continue;
}
else
{
arr.add(j);
i--;
j++;
}
}
System.out.println("missing numbers are ");
for(int r : arr)
{
System.out.println(" " + r);
}
Recently I had a similar (not exactly the same) question in a job interview and also I heard from a friend that was asked the exactly same question in an interview.
So here is an answer to the OP question and a few more variations that can be potentially asked.
The answers example are given in Java because, it's stated that:
A Java solution is preferable.
Variation 1:
Array of numbers from 1 to 100 (both inclusive) ... The numbers are randomly added to the array, but there is one random empty slot in the array
public static int findMissing1(int [] arr){
int sum = 0;
for(int n : arr){
sum += n;
}
return (100*(100+1)/2) - sum;
}
Explanation:
This solution (as many other solutions posted here) is based on the formula of Triangular number, which gives us the sum of all natural numbers from 1 to n (in this case n is 100). Now that we know the sum that should be from 1 to 100 - we just need to subtract the actual sum of existing numbers in given array.
Variation 2:
Array of numbers from 1 to n (meaning that the max number is unknown)
public static int findMissing2(int [] arr){
int sum = 0, max = 0;
for(int n : arr){
sum += n;
if(n > max) max = n;
}
return (max*(max+1)/2) - sum;
}
Explanation:
In this solution, since the max number isn't given - we need to find it. After finding the max number - the logic is the same.
Variation 3:
Array of numbers from 1 to n (max number is unknown), there is two random empty slots in the array
public static int [] findMissing3(int [] arr){
int sum = 0, max = 0, misSum;
int [] misNums = {};//empty by default
for(int n : arr){
sum += n;
if(n > max) max = n;
}
misSum = (max*(max+1)/2) - sum;//Sum of two missing numbers
for(int n = Math.min(misSum, max-1); n > 1; n--){
if(!contains(n, arr)){
misNums = new int[]{n, misSum-n};
break;
}
}
return misNums;
}
private static boolean contains(int num, int [] arr){
for(int n : arr){
if(n == num)return true;
}
return false;
}
Explanation:
In this solution, the max number isn't given (as in the previous), but it can also be missing of two numbers and not one. So at first we find the sum of missing numbers - with the same logic as before. Second finding the smaller number between missing sum and the last (possibly) missing number - to reduce unnecessary search. Third since Javas Array (not a Collection) doesn't have methods as indexOf or contains, I added a small reusable method for that logic. Fourth when first missing number is found, the second is the subtract from missing sum.
If only one number is missing, then the second number in array will be zero.
Variation 4:
Array of numbers from 1 to n (max number is unknown), with X missing (amount of missing numbers are unknown)
public static ArrayList<Integer> findMissing4(ArrayList<Integer> arr){
int max = 0;
ArrayList<Integer> misNums = new ArrayList();
int [] neededNums;
for(int n : arr){
if(n > max) max = n;
}
neededNums = new int[max];//zero for any needed num
for(int n : arr){//iterate again
neededNums[n == max ? 0 : n]++;//add one - used as index in second array (convert max to zero)
}
for(int i=neededNums.length-1; i>0; i--){
if(neededNums[i] < 1)misNums.add(i);//if value is zero, than index is a missing number
}
return misNums;
}
Explanation:
In this solution, as in the previous, the max number is unknown and there can be missing more than one number, but in this variation, we don't know how many numbers are potentially missing (if any). The beginning of the logic is the same - find the max number. Then I initialise another array with zeros, in this array index indicates the potentially missing number and zero indicates that the number is missing. So every existing number from original array is used as an index and its value is incremented by one (max converted to zero).
Note
If you want examples in other languages or another interesting variations of this question, you are welcome to check my Github repository for Interview questions & answers.
(sum of 1 to n) - (sum of all values in the array) = missing number
int sum = 0;
int idx = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) idx = i; else sum += arr[i];
}
System.out.println("missing number is: " + (5050 - sum) + " at index " + idx);
On a similar scenario, where the array is already sorted, it does not include duplicates and only one number is missing, it is possible to find this missing number in log(n) time, using binary search.
public static int getMissingInt(int[] intArray, int left, int right) {
if (right == left + 1) return intArray[right] - 1;
int pivot = left + (right - left) / 2;
if (intArray[pivot] == intArray[left] + (intArray[right] - intArray[left]) / 2 - (right - left) % 2)
return getMissingInt(intArray, pivot, right);
else
return getMissingInt(intArray, left, pivot);
}
public static void main(String args[]) {
int[] array = new int[]{3, 4, 5, 6, 7, 8, 10};
int missingInt = getMissingInt(array, 0, array.length-1);
System.out.println(missingInt); //it prints 9
}
Well, use a bloom filter.
int findmissing(int arr[], int n)
{
long bloom=0;
int i;
for(i=0; i<;n; i++)bloom+=1>>arr[i];
for(i=1; i<=n, (bloom<<i & 1); i++);
return i;
}
This is c# but it should be pretty close to what you need:
int sumNumbers = 0;
int emptySlotIndex = -1;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == 0)
emptySlotIndex = i;
sumNumbers += arr[i];
}
int missingNumber = 5050 - sumNumbers;
The solution that doesn't involve repetitive additions or maybe the n(n+1)/2 formula doesn't get to you at an interview time for instance.
You have to use an array of 4 ints (32 bits) or 2 ints (64 bits). Initialize the last int with (-1 & ~(1 << 31)) >> 3. (the bits that are above 100 are set to 1) Or you may set the bits above 100 using a for loop.
Go through the array of numbers and set 1 for the bit position corresponding to the number (e.g. 71 would be set on the 3rd int on the 7th bit from left to right)
Go through the array of 4 ints (32 bit version) or 2 ints(64 bit version)
public int MissingNumber(int a[])
{
int bits = sizeof(int) * 8;
int i = 0;
int no = 0;
while(a[i] == -1)//this means a[i]'s bits are all set to 1, the numbers is not inside this 32 numbers section
{
no += bits;
i++;
}
return no + bits - Math.Log(~a[i], 2);//apply NOT (~) operator to a[i] to invert all bits, and get a number with only one bit set (2 at the power of something)
}
Example: (32 bit version) lets say that the missing number is 58. That means that the 26th bit (left to right) of the second integer is set to 0.
The first int is -1 (all bits are set) so, we go ahead for the second one and add to "no" the number 32. The second int is different from -1 (a bit is not set) so, by applying the NOT (~) operator to the number we get 64. The possible numbers are 2 at the power x and we may compute x by using log on base 2; in this case we get log2(64) = 6 => 32 + 32 - 6 = 58.
Hope this helps.
I think the easiest and possibly the most efficient solution would be to loop over all entries and use a bitset to remember which numbers are set, and then test for 0 bit. The entry with the 0 bit is the missing number.
This is not a search problem. The employer is wondering if you have a grasp of a checksum. You might need a binary or for loop or whatever if you were looking for multiple unique integers, but the question stipulates "one random empty slot." In this case we can use the stream sum. The condition: "The numbers are randomly added to the array" is meaningless without more detail. The question does not assume the array must start with the integer 1 and so tolerate with the offset start integer.
int[] test = {2,3,4,5,6,7,8,9,10, 12,13,14 };
/*get the missing integer*/
int max = test[test.length - 1];
int min = test[0];
int sum = Arrays.stream(test).sum();
int actual = (((max*(max+1))/2)-min+1);
//Find:
//the missing value
System.out.println(actual - sum);
//the slot
System.out.println(actual - sum - min);
Success time: 0.18 memory: 320576 signal:0
I found this beautiful solution here:
http://javaconceptoftheday.com/java-puzzle-interview-program-find-missing-number-in-an-array/
public class MissingNumberInArray
{
//Method to calculate sum of 'n' numbers
static int sumOfNnumbers(int n)
{
int sum = (n * (n+1))/ 2;
return sum;
}
//Method to calculate sum of all elements of array
static int sumOfElements(int[] array)
{
int sum = 0;
for (int i = 0; i < array.length; i++)
{
sum = sum + array[i];
}
return sum;
}
public static void main(String[] args)
{
int n = 8;
int[] a = {1, 4, 5, 3, 7, 8, 6};
//Step 1
int sumOfNnumbers = sumOfNnumbers(n);
//Step 2
int sumOfElements = sumOfElements(a);
//Step 3
int missingNumber = sumOfNnumbers - sumOfElements;
System.out.println("Missing Number is = "+missingNumber);
}
}
function solution($A) {
// code in PHP5.5
$n=count($A);
for($i=1;$i<=$n;$i++) {
if(!in_array($i,$A)) {
return (int)$i;
}
}
}
Finding the missing number from a series of numbers. IMP points to remember.
the array should be sorted..
the Function do not work on multiple missings.
the sequence must be an AP.
public int execute2(int[] array) {
int diff = Math.min(array[1]-array[0], array[2]-array[1]);
int min = 0, max = arr.length-1;
boolean missingNum = true;
while(min<max) {
int mid = (min + max) >>> 1;
int leftDiff = array[mid] - array[min];
if(leftDiff > diff * (mid - min)) {
if(mid-min == 1)
return (array[mid] + array[min])/2;
max = mid;
missingNum = false;
continue;
}
int rightDiff = array[max] - array[mid];
if(rightDiff > diff * (max - mid)) {
if(max-mid == 1)
return (array[max] + array[mid])/2;
min = mid;
missingNum = false;
continue;
}
if(missingNum)
break;
}
return -1;
}
One thing you could do is sort the numbers using quick sort for instance. Then use a for loop to iterate through the sorted array from 1 to 100. In each iteration, you compare the number in the array with your for loop increment, if you find that the index increment is not the same as the array value, you have found your missing number as well as the missing index.
Below is the solution for finding all the missing numbers from a given array:
public class FindMissingNumbers {
/**
* The function prints all the missing numbers from "n" consecutive numbers.
* The number of missing numbers is not given and all the numbers in the
* given array are assumed to be unique.
*
* A similar approach can be used to find all no-unique/ unique numbers from
* the given array
*
* #param n
* total count of numbers in the sequence
* #param numbers
* is an unsorted array of all the numbers from 1 - n with some
* numbers missing.
*
*/
public static void findMissingNumbers(int n, int[] numbers) {
if (n < 1) {
return;
}
byte[] bytes = new byte[n / 8];
int countOfMissingNumbers = n - numbers.length;
if (countOfMissingNumbers == 0) {
return;
}
for (int currentNumber : numbers) {
int byteIndex = (currentNumber - 1) / 8;
int bit = (currentNumber - byteIndex * 8) - 1;
// Update the "bit" in bytes[byteIndex]
int mask = 1 << bit;
bytes[byteIndex] |= mask;
}
for (int index = 0; index < bytes.length - 2; index++) {
if (bytes[index] != -128) {
for (int i = 0; i < 8; i++) {
if ((bytes[index] >> i & 1) == 0) {
System.out.println("Missing number: " + ((index * 8) + i + 1));
}
}
}
}
// Last byte
int loopTill = n % 8 == 0 ? 8 : n % 8;
for (int index = 0; index < loopTill; index++) {
if ((bytes[bytes.length - 1] >> index & 1) == 0) {
System.out.println("Missing number: " + (((bytes.length - 1) * 8) + index + 1));
}
}
}
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<Integer>();
int n = 128;
int m = 5;
for (int i = 1; i <= n; i++) {
arrayList.add(i);
}
Collections.shuffle(arrayList);
for (int i = 1; i <= 5; i++) {
System.out.println("Removing:" + arrayList.remove(i));
}
int[] array = new int[n - m];
for (int i = 0; i < (n - m); i++) {
array[i] = arrayList.get(i);
}
System.out.println("Array is: " + Arrays.toString(array));
findMissingNumbers(n, array);
}
}
Lets say you have n as 8, and our numbers range from 0-8 for this example
we can represent the binary representation of all 9 numbers as follows
0000
0001
0010
0011
0100
0101
0110
0111
1000
in the above sequence there is no missing numbers and in each column the number of zeros and ones match, however as soon as you remove 1 value lets say 3 we get a in balance in the number of 0's and 1's across the columns. If the number of 0's in a column is <= the number of 1's our missing number will have a 0 at this bit position, otherwise if the number of 0's > the number of 1's at this bit position then this bit position will be a 1. We test the bits left to right and at each iteration we throw away half of the array for the testing of the next bit, either the odd array values or the even array values are thrown away at each iteration depending on which bit we are deficient on.
The below solution is in C++
int getMissingNumber(vector<int>* input, int bitPos, const int startRange)
{
vector<int> zeros;
vector<int> ones;
int missingNumber=0;
//base case, assume empty array indicating start value of range is missing
if(input->size() == 0)
return startRange;
//if the bit position being tested is 0 add to the zero's vector
//otherwise to the ones vector
for(unsigned int i = 0; i<input->size(); i++)
{
int value = input->at(i);
if(getBit(value, bitPos) == 0)
zeros.push_back(value);
else
ones.push_back(value);
}
//throw away either the odd or even numbers and test
//the next bit position, build the missing number
//from right to left
if(zeros.size() <= ones.size())
{
//missing number is even
missingNumber = getMissingNumber(&zeros, bitPos+1, startRange);
missingNumber = (missingNumber << 1) | 0;
}
else
{
//missing number is odd
missingNumber = getMissingNumber(&ones, bitPos+1, startRange);
missingNumber = (missingNumber << 1) | 1;
}
return missingNumber;
}
At each iteration we reduce our input space by 2, i.e N, N/2,N/4 ... = O(log N), with space O(N)
//Test cases
[1] when missing number is range start
[2] when missing number is range end
[3] when missing number is odd
[4] when missing number is even
Solution With PHP $n = 100;
$n*($n+1)/2 - array_sum($array) = $missing_number
and array_search($missing_number) will give the index of missing number
Here program take time complexity is O(logn) and space complexity O(logn)
public class helper1 {
public static void main(String[] args) {
int a[] = {1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12};
int k = missing(a, 0, a.length);
System.out.println(k);
}
public static int missing(int[] a, int f, int l) {
int mid = (l + f) / 2;
//if first index reached last then no element found
if (a.length - 1 == f) {
System.out.println("missing not find ");
return 0;
}
//if mid with first found
if (mid == f) {
System.out.println(a[mid] + 1);
return a[mid] + 1;
}
if ((mid + 1) == a[mid])
return missing(a, mid, l);
else
return missing(a, f, mid);
}
}
public class MissingNumber {
public static void main(String[] args) {
int array[] = {1,2,3,4,6};
int x1 = getMissingNumber(array,6);
System.out.println("The Missing number is: "+x1);
}
private static int getMissingNumber(int[] array, int i) {
int acctualnumber =0;
int expectednumber = (i*(i+1)/2);
for (int j : array) {
acctualnumber = acctualnumber+j;
}
System.out.println(acctualnumber);
System.out.println(expectednumber);
return expectednumber-acctualnumber;
}
}
Use sum formula,
class Main {
// Function to ind missing number
static int getMissingNo (int a[], int n) {
int i, total;
total = (n+1)*(n+2)/2;
for ( i = 0; i< n; i++)
total -= a[i];
return total;
}
/* program to test above function */
public static void main(String args[]) {
int a[] = {1,2,4,5,6};
int miss = getMissingNo(a,5);
System.out.println(miss);
}
}
Reference http://www.geeksforgeeks.org/find-the-missing-number/
simple solution with test data :
class A{
public static void main(String[] args){
int[] array = new int[200];
for(int i=0;i<100;i++){
if(i != 51){
array[i] = i;
}
}
for(int i=100;i<200;i++){
array[i] = i;
}
int temp = 0;
for(int i=0;i<200;i++){
temp ^= array[i];
}
System.out.println(temp);
}
}
//Array is shorted and if writing in C/C++ think of XOR implementations in java as follows.
int num=-1;
for (int i=1; i<=100; i++){
num =2*i;
if(arr[num]==0){
System.out.println("index: "+i+" Array position: "+ num);
break;
}
else if(arr[num-1]==0){
System.out.println("index: "+i+ " Array position: "+ (num-1));
break;
}
}// use Rabbit and tortoise race, move the dangling index faster,
//learnt from Alogithimica, Ameerpet, hyderbad**
If the array is randomly filled, then at the best you can do a linear search in O(n) complexity. However, we could have improved the complexity to O(log n) by divide and conquer approach similar to quick sort as pointed by giri given that the numbers were in ascending/descending order.
This Program finds missing numbers
<?php
$arr_num=array("1","2","3","5","6");
$n=count($arr_num);
for($i=1;$i<=$n;$i++)
{
if(!in_array($i,$arr_num))
{
array_push($arr_num,$i);print_r($arr_num);exit;
}
}
?>
Now I'm now too sharp with the Big O notations but couldn't you also do something like (in Java)
for (int i = 0; i < numbers.length; i++) {
if(numbers[i] != i+1){
System.out.println(i+1);
}
}
where numbers is the array with your numbers from 1-100.
From my reading of the question it did not say when to write out the missing number.
Alternatively if you COULD throw the value of i+1 into another array and print that out after the iteration.
Of course it might not abide by the time and space rules. As I said. I have to strongly brush up on Big O.
========Simplest Solution for sorted Array===========
public int getMissingNumber(int[] sortedArray)
{
int missingNumber = 0;
int missingNumberIndex=0;
for (int i = 0; i < sortedArray.length; i++)
{
if (sortedArray[i] == 0)
{
missingNumber = (sortedArray[i + 1]) - 1;
missingNumberIndex=i;
System.out.println("missingNumberIndex: "+missingNumberIndex);
break;
}
}
return missingNumber;
}
Another homework question. A sequential search is the best that you can do. As for a Java solution, consider that an exercise for the reader. :P

Categories