Find consecutive number of 1's - java

I am trying to find the number of consecutive 1's in a binary.
Example: Convert Decimal number to Binary and find consecutive 1's
static int count = 0;
static int max = 0;
static int index = 1;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
scan.close();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);
for (int i = 0; i < b.length(); i++) {
if (arr[i] == index) {
count++;
} else {
count = 0;
}
if (count > max) {
max = count;
}
}
System.out.println(max);
}
I am always getting 0. It seems as if the condition is not working in my code. Could you please provide your suggestion on where am I going wrong with this?

Your qusetion is not so clear but AFAIU from your algorithm, you're trying to find number of most repeated 1's. The issue is that when you're doing comparision if (arr[i] == index), the comparison is done with a char and integer because type of arr is char array. Isn't it? To overcome it either you can convert the char array into integer or convert the integer index value into char. I do this to overcome it.
if (arr[i] == index + '0')
It is not an really elegant solution. I assume that you're a student and want you to show what's wrong. If I want to do something like this, I use,
private static int maxConsecutiveOnes(int x) {
// Initialize result
int count = 0;
// Count the number of iterations to
// reach x = 0.
while (x!=0) {
// This operation reduces length
// of every sequence of 1s by one.
x = (x & (x << 1));
count++;
}
return count;
}
Its trick is,
11101111 (x)
& 11011110 (x << 1)
----------
11001110 (x & (x << 1))
^ ^
| |
trailing 1 removed

As I understand correctly, you want to count maximum length of the group of 1 in the binary representation of the int value. E.g. for 7917=0b1111011101101 result will be 4 (we have following groups of 1: 1, 2, 3, 4).
You could use bit operations (and avoid to string convertation). You have one counter (to count amount of 1 in the current group) and max with maximum of all such amounts. All you need is just to check lowest bit for 1 and then rotate value to the right until it becomes 0, like getMaxConsecutiveSetBit1.
Or just do it in a very simple way - convert it to the binary string and count amount of 1 characters in it, like getMaxConsecutiveSetBit2. Also have one counter + max. Do not forget, that char in Java is an int on the JVM level. So you do not have compilation problem with compare char with int value 1, but this is wrong. To check if character is 1, you have to use character - '1'.
public static void main(String[] args) {
try (Scanner scan = new Scanner(System.in)) {
int val = scan.nextInt();
System.out.println(Integer.toBinaryString(val));
System.out.println(getMaxConsecutiveSetBit1(val));
System.out.println(getMaxConsecutiveSetBit2(val));
}
}
public static int getMaxConsecutiveSetBit1(int val) {
int max = 0;
int cur = 0;
while (val != 0) {
if ((val & 0x1) != 0)
cur++;
else {
max = Math.max(max, cur);
cur = 0;
}
val >>>= 1;
}
return Math.max(max, cur);
}
public static int getMaxConsecutiveSetBit2(int val) {
int max = 0;
int cur = 0;
for (char ch : Integer.toBinaryString(val).toCharArray()) {
if (ch == '1')
cur++;
else {
max = Math.max(max, cur);
cur = 0;
}
}
return Math.max(max, cur);
}

Change type of index variable from int to char:
static char index = 1;
to let the comparison made in this line:
if (arr[i] == index)
do its job. Comparing int 1 (in your code this is the value stored in index variable) with char '1' (in your example it's currently checked element of arr[]) checks if ASCII code of given char is equal to int value of 1. This comparison is never true as char '1' has an ASCII code 49 and this is the value that is being compared to value of 1 (49 is never equal to 1).
You might want to have a look at ASCII codes table in the web to see that all characters there have assigned corresponding numeric values. You need to be aware that these values are taken into consideration when comparing char to int with == operaror.
When you change mentioned type of index to char, comparison works fine and your code seems to be fixed.

Using your for loop structure and changing a few things around while also adding some other stats to report which could be useful. I count the total number of 1's in the number, the number of consecutive 1's (groups of 1's), and the greatest number of consecutive 1's. Also your for loop was looping based on the string length and not the array's length which is just sort of nit picky. Here is the code
int count = 0;
int max = 0;
char index = '1';
int consecutiveOnePairs = 0;
int numberOfOnes = 0;
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);
for (int i = 0; i < arr.length; i++) {
if (arr[i] == index)
{
count++;
numberOfOnes++;
}
if((i + 1 == arr.length && count > 1) || arr[i] != index)
{
if(count > 1)
consecutiveOnePairs++;
if (count > max)
max = count;
count = 0;
}
}
System.out.println("Total Number of 1's in " + n + " is " + numberOfOnes);
System.out.println("Total Number of Consecutive 1's in " + n + " is " + consecutiveOnePairs);
System.out.println("Greatest Number of Consecutive 1's in " + n + " is " + max);
scan.close();
Output
13247
11001110111111
Total Number of 1's in 13247 is 11
Total Number of Consecutive 1's in 13247 is 3
Greatest Number of Consecutive 1's in 13247 is 6
511
111111111
Total Number of 1's in 511 is 9
Total Number of Consecutive 1's in 511 is 1
Greatest Number of Consecutive 1's in 511 is 9
887
1101110111
Total Number of 1's in 887 is 8
Total Number of Consecutive 1's in 887 is 3
Greatest Number of Consecutive 1's in 887 is 3

If you use Java 8, you can try this snippet:
public int maxOneConsecutive(int x)
{
String intAsBinaryStr = Integer.toBinaryString(x);
String[] split = intAsBinaryStr.split("0");
return Arrays.stream(split)
.filter(str -> !str.isEmpty())
.map(String::length)
.max(Comparator.comparingInt(a -> a)).orElse(0);
}

Related

Find middle digit in an integer in Java

I have an integer in java "1234567" and my program finds middle digit in a set of integer, is there more optimized way than below code?. Recently asked in java interview.
What I have done is first find no of digits, first, last and middle indexes. Then find middle digit again iterating on same integer. Please advice some optimization.
int a1 = 1234567;
int a = a1;
// calculate length
int noOfDigits = 0;
while(a!=0)
{
a = a/10;
noOfDigits++;
}
int first = 0;
int last = noOfDigits-1;
int middle = (first+last)/2;
boolean midExists = ((a1%2)==1);
System.out.println(" digits: "+a1);
System.out.println(" no of digits "+noOfDigits);
System.out.println(" first "+first);
System.out.println(" last " + last);
if(midExists)
{
System.out.println(" middle " + middle);
int i = last;
int middleDigit = 0;
a = a1;
while(i != middle)
{
a = (a / 10);
middleDigit = (a%10);
i--;
}
System.out.println("middle digit: " + middleDigit);
}
else
System.out.println(" Mid not Exists.. ");
Program Output:
digits: 1234567
no of digits 7
first 0
last 6
middle 3
middle digit: 4
You can also do this in one pass. Idea is that first store the integer in the another variable. Then move two digits to the left in one integer while only one digit in the another one.
int a1 = 1234567;
int a2 = a1;
int flag=0;
while(a2>0)
{
a2/=10; //Moves to the left by one digit
if(a2==0) //If there are odd no. of digits
{
flag=1;
break;
}
a2/=10; //Moves to the left by one digit
a1/=10; //Moves to the left by one digit
}
System.out.print(flag!=1?"No Mid Exists":a1%10);
Your "math" is working correctly. The one thing you can: compute the length (number of digits) within your number upfront, to avoid "iterating" the number twice - so you can determine if that number of digits is even or odd without "iterating" the number:
int n = 1234;
int length = (int)(Math.log10(n)+1);
should give you 4 for 1234, and 5 for 12345.
But beyond that: you can express information in different ways. For example: you can turn an int value into a string.
String asStr = Integer.toString(123456);
And now: you can easily check the length of that string; and you can directly access the corresponding character!
The only thing to keep in mind: characters representing numbers like '1', '2', ... have different numerical values as int 1, 2, ... (see an ASCII table; as '1' is 49 when regarding its numerical value)!
this answer has less code, but wouldn't take much in performance i think:
int a1 = 12334;
int a = a1;
int middle = 0;
int noOfDigits = 0;
while (a1 != 0) {
a1 = a1 / 10;
noOfDigits++;
}
if (noOfDigits % 2 == 1) {
for (int i = 0; i < (noOfDigits / 2) + 1; i++) {
middle = a % 10;
a = a / 10;
}
System.out.println(middle);
} else {
System.out.println("No mid existing");
}
Using only math
int num = 123406789;
int countDigits = (int)Math.ceil(Math.log10(num));
int midIndex = (int)Math.ceil(countDigits/2);
int x = num / (int)Math.pow(10, midIndex);
int middleDigit = x % 10;
System.out.println(middleDigit);

Error with multiplying char with a number and add with char ( Big Java Ex 6.2)

Currently going through an exercise in my book, but i'm stuck ( I havent learned arrays yet, this chapter is on loops nested loops and for loops)
The first part of the problem is to take a credit card number and then sum every other number backwards
Consider 4358 9795, which should output the sum 5+7+8 + 3 = 23.
Heres my solution which isn't working
class Checkit{
private String creditNum;
private int sum;
public Checkit(String creditNum)
{
this.creditNum = creditNum;
sum = 0;
}
public int getSum()
{
for (int i = creditNum.length() ; i > 0 ; i--)
{
char ch = creditNum.charAt(i-1);
if(i%2 == 1 )
{
sum+=ch;
}
}
return sum;
}
}
public class test{
public static void main(String [] args)
{
Checkit sampleNumber = new Checkit("4358 9795");
System.out.println(sampleNumber.getSum());
}
}
I'm not exactly sure whats wrong with my logic. ch is taking all of the values of my credit card number 5,7,8,3. But for some reason the sum is messing up.
BONUS PART
Take Each number that wasn't added and double it, so 9+9 + 5 + 4, double each of those terms ( that becomes 18 + 18 + 10 + 8), and then get the sum of 1 + 8 + 1 + 8 + 1 + 0 + 8.
I tried the bonus part, but for some reason every time I get 9, 9, 5,4 and times that char value by 2, I get letters. I don't think I can multiply chars by integers, so should I do conversions? Note I didn't learn arrays yet
NEW CODE
class Checkit {
private String creditCardNum;
private int sum;
public Checkit(String creditCardNum) {
sum = 0;
this.creditCardNum = creditCardNum;
}
public int getSum() {
creditCardNum = creditCardNum.replaceAll("\\s+", "");
for (int i = creditCardNum.length(); i > 0; i--) {
char ch = creditCardNum.charAt(i - 1);
if (i % 2 == 0) {
sum += Character.getNumericValue(ch);
}
}
return sum;
}
public int doubleDigitSum() {
sum = 0;
creditCardNum = creditCardNum.replaceAll("\\s", "");
for (int i = creditCardNum.length(); i > 0; i--) {
char ch = creditCardNum.charAt(i - 1);
if (i % 2 == 1) {
int newChar = Character.getNumericValue(ch) * 2;
String newCharString = Integer.toString(newChar);
for (int j = 0; j < newCharString.length(); j++) {
char sumThis = newCharString.charAt(j);
sum += Character.getNumericValue(sumThis);
}
}
}
return sum;
}
}
public class DataSet{
public static void main(String [] args) {
Checkit data = new Checkit("4358 9795");
System.out.println(data.getSum());
System.out.println(data.doubleDigitSum());
}
}
You're adding char values rather than int values. Replace sum+=ch; with
sum += ch - '0';
The reason why this works as opposed to the original solution is that when you're adding char values to an int value, the char is converted to a decimal via its ASCII value. For example, '5' has a ASCII dec value of 53. However, '5' - '0' equals 5. More on these ASCII values can be found here, http://www.asciitable.com/
Your issue is that you are not converting the char to an integer:
public int getSum()
{
for (int i = creditNum.length() ; i > 0 ; i--)
{
char ch = creditNum.charAt(i-1);
if(i%2 == 1 )
{
sum+=ch;
}
}
return sum;
}
Fun fact that's causing your error - chars are numbers! They're simply a number that represents the ascii character code of the letter. So when you add them to a sum, Java is OK with that and just adds the corresponding number for the char '8' for example, which is 56.
To make your code work, you need to properly convert to an integer:
public int getSum()
{
for (int i = creditNum.length() ; i > 0 ; i--)
{
char ch = creditNum.charAt(i-1);
if(i%2 == 1)
{
sum+=Character.getNumericValue(ch);
}
}
return sum;
}
for (int i = creditNum.length() ; i > 0 ; i--) {
char ch = creditNum.charAt(i-1);
First iteration thru loop gets IndexOutOfBounds exception. And then you never check the initial character of the credit card number, since your termination criterion is ( i > 0 ), not (i >= 0)
And why not just use i -= 2 for the increment instead of the if-check?

How can I get max number that consists of some digits of an integer number

I have a number. This number has many digits. I want to write a function which returns the largest number that consists of some digits of that number. While getting that largest number, the sequence of the digits should not change.
int myFunction(int n, int cat){
...
return max;
}
If n = 38462637 and cat = 3 the function has to return 86637, i.e. if cat = 3 the function is expected to return 5-digit number, as 8 - 3 = 5. The original number has many variations of 5 digits numbers, but the largest possible number is 86637. In this case, the most important requirement is that the digits should not change their place.
Be greedy - select the largest digit that can be leftmost in the answer(if there are several positions where this digit appears, choose its leftmost occurance). A digit may be leftmost if it is not 0 and we have at least n - cat - 1 digits to the right of it.
After that use the same algorithm to create the largest number on the right of the position of this digit that has exactly n - cat - 1 digits. Continue iterating until you have your number composed. Only note that the digits you select after the first iteration may be zero(as they will no longer be leftmost in the resulting number)
EDIT: best solution that uses the algorithm described above - use range minimum query to compute the highest value that is possible for each consecutive digit position. In theory this can be done in constant time per query and linear extra memory using linear precomputation, but the algorithm is so complex and hard to implement that it will only give you improvement for really big values of n. I personally suggest using a segment tree approach that will result in O(n*log(n)) time complexity.
This is probably a bit overcomplicated, but it seems to work:
public static int myFunction(int n, int cat) {
String numString = String.valueOf(n);
int finalLength = numString.length() - cat;
int[] positions = new int[finalLength];
StringBuilder answer = new StringBuilder();
for (int i = 0; i < finalLength; i++) {
for (int j = (i == 0 ? i : positions[i - 1] + 1); j <= numString.length() - finalLength + i; j++) {
if (positions[i] == 0 || numString.charAt(j) > numString.charAt(positions[i]) ) {
positions[i] = j;
}
}
answer.append(numString.charAt(positions[i]));
}
return Integer.parseInt(answer.toString());
}
[EDIT]: A cleaner version without all the String nonsense:
public static int myFunction(int n, int cat) {
List<Integer> digits = new ArrayList<Integer>();
int number = n;
while (number > 0) {
digits.add(number % 10);
number /= 10;
}
int finalLength = digits.size() - cat;
int lastIndex = digits.size();
int answer = 0;
for (int i = 0; i < finalLength; i++) {
int highestDigit = -1;
for (int j = lastIndex - 1; j >= finalLength - i - 1; j--) {
if (digits.get(j) > highestDigit) {
highestDigit = digits.get(j);
lastIndex = j;
}
}
answer = answer * 10 + highestDigit;
}
return answer;
}
If you have access to the code, store the number as a string with a seperator (space, comma, etc) in it, then use the string separator function to put each number (string character) into it's own array location. Parse the string array and make an integer array. Then run a quick sort on the array. When that is done, take the first X number of integers and that is your number.

Iterate through each digit in a number

I am trying to create a program that will tell if a number given to it is a "Happy Number" or not. Finding a happy number requires each digit in the number to be squared, and the result of each digit's square to be added together.
In Python, you could use something like this:
SQUARE[d] for d in str(n)
But I can't find how to iterate through each digit in a number in Java. As you can tell, I am new to it, and can't find an answer in the Java docs.
You can use a modulo 10 operation to get the rightmost number and then divide the number by 10 to get the next number.
long addSquaresOfDigits(int number) {
long result = 0;
int tmp = 0;
while(number > 0) {
tmp = number % 10;
result += tmp * tmp;
number /= 10;
}
return result;
}
You could also put it in a string and turn that into a char array and iterate through it doing something like Math.pow(charArray[i] - '0', 2.0);
Assuming the number is an integer to begin with:
int num = 56;
String strNum = "" + num;
int strLength = strNum.length();
int sum = 0;
for (int i = 0; i < strLength; ++i) {
int digit = Integer.parseInt(strNum.charAt(i));
sum += (digit * digit);
}
I wondered which method would be quickest to split up a positive number into its digits in Java, String vs modulo
public static ArrayList<Integer> splitViaString(long number) {
ArrayList<Integer> result = new ArrayList<>();
String s = Long.toString(number);
for (int i = 0; i < s.length(); i++) {
result.add(s.charAt(i) - '0');
}
return result; // MSD at start of list
}
vs
public static ArrayList<Integer> splitViaModulo(long number) {
ArrayList<Integer> result = new ArrayList<>();
while (number > 0) {
int digit = (int) (number % 10);
result.add(digit);
number /= 10;
}
return result; // LSD at start of list
}
Testing each method by passing Long.MAX_VALUE 10,000,000 times, the string version took 2.090 seconds and the modulo version 2.334 seconds. (Oracle Java 8 on 64bit Ubuntu running in Eclipse Neon)
So not a lot in it really, but I was a bit surprised that String was faster
In the above example we can use:
int digit = Character.getNumericValue(strNum.charAt(i));
instead of
int digit = Integer.parseInt(strNum.charAt(i));
You can turn the integer into a string and iterate through each char in the string. As you do that turn that char into an integer
This code returns the first number (after 1) that fits your description.
public static void main(String[] args) {
int i=2;
// starting the search at 2, since 1 is also a happy number
while(true) {
int sum=0;
for(char ch:(i+"").toCharArray()) { // casting to string and looping through the characters.
int j=Character.getNumericValue(ch);
// getting the numeric value of the current char.
sum+=Math.pow(j, j);
// adding the current digit raised to the power of itself to the sum.
}
if(sum==i) {
// if the sum is equal to the initial number
// we have found a number that fits and exit.
System.out.println("found: "+i);
break;
}
// otherwise we keep on searching
i++;
}
}

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