How do I count numbers that contain one digit, but not another? - java

I recently came across an interview question which although had an immediately obvious solution, I struggled to find a more efficient one.
The actual question involved counting numbers from a to b (up to 2^64) which satisfied having either the digit 6 or 8, but not both. They called it a 'lucky number'. So for example:
126 - lucky
88 - lucky
856 - not lucky
The obvious thought was to brute force it by testing each number between a and b as a string, to check for the relevant characters. However, this was prohibitively slow as expected.
A much better solution that I tried, involved first computing all the 'lucky numbers' which had the number of digits between the number of digits that a and b have (by counting possible combinations):
long n = 0;
for (int occurrences = 1; occurrences <= maxDigits; occurrences++) {
n += (long) Math.pow(8, digits - occurrences) * choose(digits, occurrences);
}
return 2 * n;
and then using the brute force method to compute the number of extra lucky numbers that I had counted. So for example, if a = 3 and b = 21, I could count the number of 1 and 2 digit lucky numbers, then subtract the count of those in [1, 3) and (21, 99].
However, although this was a massive improvement, the brute force element still slowed it down way too much for most cases.
I feel like there must be something I am missing, as the rest of the interview questions were relatively simple. Does anyone have any idea of a better solution?
Although I have tagged this question in Java, help in any other languages or pseudocode would be equally appreciated.

I would say you are at the right track. The gut feeling is that dealing with the a and b separately is easier. Making a function count_lucky_numbers_below(n) allows
return count_lucky_numbers_below(b) - count_lucky_numbers_below(a);
The combinatorial approach is definitely a way to go (just keep in mind that the sum is actually equal to 9**n - 8**n, and there is no need to compute the binomial coefficients).
The final trick is to recurse down by a numbeer of digits.
Lets say n is an N-digit number, and the most significant digit is 5. Each set of N-digit numbers starting with a smaller digit contributes S = 9**(N-1) - 8**(N-1) to the total; you immediately have 5*S of lucky numbers. To deal with the remainder, you need to compute the lucky numbers for the N-1-digit tail.
Of course, care must be taken if the most significant digit is above 5. You need to special case it being 6 or 8, but it doesn't seem to be too complicated.

In the end the answer from #user58697 pushed me in the right direction towards finding a solution. With my (albeit extremely primitive) benchmark, it handles 1 to 2^63 - 1 in less than 2 nanoseconds, so it is definitely fast enough. However it is still more verbose than I would have liked, especially given that I was originally expected to write it in half an hour, so I feel like there is still an easier solution that gives comparable performance.
long countLuckyNumbersBetween(long a, long b) {
return countLuckyNumbersBelow(b) - countLuckyNumbersBelow(a - 1);
}
long countLuckyNumbersBelow(long n) {
return countNumbers(n, 6, 8) + countNumbers(n, 8, 6);
}
/**
* Counts the natural numbers in [0, {to}] that have {including} as a digit, but not {excluding}.
* {excluding} should be in (0, 9] or -1 to exclude no digit.
*/
long countNumbers(long to, int including, int excluding) {
if (including == -1) return 0;
if (to < 10) {
if (to >= including) {
return 1;
} else {
return 0;
}
}
int nSignificand = significand(to);
int nDigits = countDigits(to);
long nTail = to % (long) Math.pow(10, nDigits - 1);
// The count of numbers in [0, 10^(nDigits-1)) that include and exclude the relevant digits
long bodyCount;
if (excluding == -1) {
bodyCount = (long) (Math.pow(10, nDigits - 1) - Math.pow(9, nDigits - 1));
} else {
bodyCount = (long) (Math.pow(9, nDigits - 1) - Math.pow(8, nDigits - 1));
}
long count = 0;
for (int i = 0; i < nSignificand; i++) {
if (i == including) {
if (excluding == -1) {
count += Math.pow(10, nDigits - 1);
} else {
count += Math.pow(9, nDigits - 1);
}
} else if (i != excluding) {
count += bodyCount;
}
}
if (nSignificand == including) {
count += 1 + nTail - countNumbers(nTail, excluding, -1);
} else if (nSignificand != excluding) {
count += countNumbers(nTail, including, excluding);
}
return count;
}
int significand(long n) {
while (n > 9) n /= 10;
return (int) n;
}
int countDigits(long n) {
if (n <= 1) {
return 1;
} else {
return (int) (Math.log10(n) + 1);
}
}

Here is another approach:
264 = 18446744073709551616
We can represent the number as a sum of components (one component per every digit position):
18446744073709551616 associated range of numbers
———————————————————— ———————————————————————————————————————————
0xxxxxxxxxxxxxxxxxxx => [00000000000000000000;09999999999999999999]
17xxxxxxxxxxxxxxxxxx => [10000000000000000000;17999999999999999999]
183xxxxxxxxxxxxxxxxx => [18000000000000000000;18399999999999999999]
1843xxxxxxxxxxxxxxxx => [18400000000000000000;18439999999999999999]
18445xxxxxxxxxxxxxxx => [18440000000000000000;18445999999999999999]
...
1844674407370955160x => [18446744073709551600;18446744073709551609]
18446744073709551616 => [18446744073709551610;18446744073709551616]
If we could compute the amount of lucky numbers for every component, then the sum of the amounts for every component will be the total amount for 264.
Note that every component consists of a prefix followed by xs.
Imagine that we know how many lucky numbers there are in an n-digit xx..x (i.e. numbers [0..0 - 9..9]), let's call it N(n).
Now let's look at a component 18445x..x. where 18445 is a prefix and an n-digit xx..x.
In this component we look at all numbers from 18440xx..x to 18445xx..x.
For every item 1844dxx..x we look at the prefix 1844d:
if prefix contains no 6 or 8, then it's the same as x..x without prefix => N(n) special numbers
if prefix contains 6 and no 8, then x..x cannot contain 8 => 9ⁿ special numbers
if prefix contains 8 and no 6, then x..x cannot contain 6 => 9ⁿ special numbers
if prefix contains 6 and 8 => 0 special numbers
Now let's compute N(n) — the amount of lucky numbers in an n-digit xx..x (i.e. in [0..0 - 9..9]).
We can do it iteratively:
n=1: there are only 2 possible numbers: 8 and 6 => N(1)=2.
n=2: there are 2 groups:
8 present: 8x and x8 where x is any digit except 6
6 present: 6x and x6 where x is any digit except 8
=> N(2)=4*9=34.
n=3: let's fix the 1st digit:
0xx — 5xx, 7xx, 9xx => 8 * N(2)
6xx: xx are any 2 digits except 8 => 9²
8xx: xx are any 2 digits except 6 => 9²
=> N(3) = 8*N(2) + 2*9².
n=k+1 => N(k+1) = 7*N(k) + 2*9ᵏ
Here is an implementation (not 100% tested):
public final class Numbers {
public long countLuckyNumbersBelow(BigInteger num) {
if (num.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("num < 0: " + num);
}
var numberText = num.toString();
var result = 0L;
for (var digitPosition = 0; digitPosition < numberText.length(); digitPosition++) {
result += countLuckyNumbersForComponent(numberText, digitPosition);
}
return result;
}
private long countLuckyNumbersForComponent(String numberText, int digitPosition) {
var prefixEndIdx = numberText.length() - 1 - digitPosition;
var prefixHas6s = containsChar(numberText, '6', prefixEndIdx);
var prefixHas8s = containsChar(numberText, '8', prefixEndIdx);
if (prefixHas6s && prefixHas8s) {
return 0;
}
var result = 0L;
for (var c = numberText.charAt(prefixEndIdx) - 1; c >= '0'; c--) {
var compNo6s = (!prefixHas6s) && (c != '6');
var compNo8s = (!prefixHas8s) && (c != '8');
if (compNo6s && compNo8s) {
result += countLuckyNumbers(digitPosition);
} else if (compNo6s || compNo8s) {
result += power9(digitPosition);
}
}
return result;
}
private static boolean containsChar(String text, char c, int endIdx) {
var idx = text.indexOf(c);
return (idx > 0) && (idx < endIdx);
}
private long[] countLuckyNumbersCache = {0L, 0L};
/**
* Computes how many lucky numbers are in an n-digit `xx..x`
*/
private long countLuckyNumbers(int numDigits) {
if (countLuckyNumbersCache[0] == numDigits) {
return countLuckyNumbersCache[1];
}
long N;
if (numDigits <= 1) {
N = (numDigits == 1) ? 2 : 0;
} else {
var prevN = countLuckyNumbers(numDigits - 1);
N = (8 * prevN) + (2 * power9(numDigits-1));
}
countLuckyNumbersCache[0] = numDigits;
countLuckyNumbersCache[1] = N;
return N;
}
private long[] power9Cache = {0L, 1L};
/**
* Computes 9<sup>power</sup>
*/
private long power9(int power) {
if (power9Cache[0] == power) {
return power9Cache[1];
}
long res = 1;
var p = power;
if (power > power9Cache[0]) {
p -= power9Cache[0];
res = power9Cache[1];
}
for (; p > 0; p--) {
res *= 9;
}
power9Cache[0] = power;
power9Cache[1] = res;
return res;
}
}
BTW it took me half a day, and I have no idea how is that possible to complete it in 30 minutes.
I guess your interviewers expected from you to demonstrate them your thought process.

Here is the result of my attempt.
First, let me explain a little bit what logic I used.
I used formula S = 9N — 8N (mentioned in the user58697's answer) to compute how many of N-digit numbers are lucky.
How to get this formula:
for N-digit numbers there are 10N numbers in total: N digits, each can take one of 10 values: [0-9].
if we only count numbers without 6, then each digit can only take one of 9 values [0-5,7-9] — it's 9N numbers in total
now we also want only numbers with 8.
We can easily compute how many numbers don't have both 6 and 8: digits in these numbers can only take one of 8 values [0-5,7,9] — it's 8N numbers in total.
As a result, there are S = 9N — 8N numbers which have 8 and no 6.
For numbers with 6 and without 8 the formula is the same.
Also numbers without 6 do not intersect with numbers without 8 — so we can just sum them.
And finally, since we know how to count lucky numbers for intervals [0;10N], we need to split the interval [0; our arbitrary number] into suitable sub-intervals.
For instance, we can split number 9845637 this way:
Sub-interval
Prefix
Digit
N-digit interval
0000000 - 8999999
0 - 8
000000 - 999999
9000000 - 9799999
9
0 - 7
00000 - 99999
9800000 - 9839999
98
0 - 3
0000 - 9999
9840000 - 9844999
984
0 - 4
000 - 999
9845000 - 9845599
9845
0 - 5
00 - 99
9845600 - 9845629
98456
0 - 2
0 - 9
9845630 - 9845637
Now we can compute the number for every sub-interval (just keep attention to digits in prefix — they might contains 8 or 6) and then just sum those numbers to get the final result.
Here is the code:
// Special value for 'requiredDigit': no required digit
private static char NIL = Character.MAX_VALUE;
public static long countLuckyNumbersUpTo(BigInteger number) {
if (number.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("number < 0: " + number);
}
var numberAsDigits = number.toString();
return countNumbersUpTo(numberAsDigits, '6', '8') + countNumbersUpTo(numberAsDigits, '8', '6');
}
// count all numbers in [0;'numberAsDigits'] which have 'requiredDigit' and no 'excludeDigit'
private static long countNumbersUpTo(String numberAsDigits, char requiredDigit, char excludeDigit) {
var highDigit = numberAsDigits.charAt(0);
if (numberAsDigits.length() == 1) {
return (requiredDigit != NIL)
? ((highDigit >= requiredDigit) ? 1 : 0)
: numDigitsInInterval('0', highDigit, excludeDigit);
}
var tailDigits = numberAsDigits.substring(1);
var result = 0L;
// numbers where the highest digit is in [0;`highDigit`)
var numGoodDigits = numDigitsInInterval('0', (char) (highDigit - 1), excludeDigit);
var containsRequiredDigit = (requiredDigit != NIL) && (highDigit > requiredDigit);
if (containsRequiredDigit) {
result += totalNumbers(tailDigits.length(), NIL);
numGoodDigits--;
}
if (numGoodDigits > 0) {
result += numGoodDigits * totalNumbers(tailDigits.length(), requiredDigit);
}
// remaining numbers where the highest digit is `highDigit`
if (highDigit != excludeDigit) {
var newRequiredDigit = (highDigit == requiredDigit) ? NIL : requiredDigit;
result += countNumbersUpTo(tailDigits, newRequiredDigit, excludeDigit);
}
return result;
}
private static int numDigitsInInterval(char firstDigit, char lastDigit, char excludeDigit) {
var totalDigits = lastDigit - firstDigit + 1;
return (excludeDigit <= lastDigit) ? (totalDigits - 1) : totalDigits;
}
// total numbers with given requiredDigit in [0;10^numDigits)
private static long totalNumbers(int numDigits, char requiredDigit) {
return (requiredDigit == NIL) ? pow(9, numDigits) : (pow(9, numDigits) - pow(8, numDigits));
}
private static long pow(int base, int exponent) {
return BigInteger.valueOf(base).pow(exponent).longValueExact();
}

Related

Plus one leetcode

I am doing a question on leetcode, 66. Plus One.
You are given a large integer represented as integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading 0's.
Increment the large integer by one and return the resulting array of digits.
Example 1
Input: digits = [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Incrementing by one gives 123 + 1 = 124.
Thus, the result should be [1,2,4].
My solution is:
class Solution {
public int[] plusOne(int[] digits) {
int num = 0;
for (int a : digits) {
num = 10*num + a;
}
int n=num+1;
String str=String.valueOf(n);
int arr[]=new int[str.length()];
for(int i=0;i<str.length();i++){
arr[i]=str.charAt(i)-'0';
}
return arr;
}
}
I am getting many test cases failed, one being:
Input:
[9,8,7,6,5,4,3,2,1,0]
Output:
[1,2,8,6,6,0,8,6,1,9]
Expected:
[9,8,7,6,5,4,3,2,1,1]
Can anyone help me with it?
Think before you leap. And consider the edges.
Why would they do the seemingly idiotic move of storing an number, digit by digit, in an int array? Makes no sense, right?
Except... computers aren't magic. int can't represent any number. A computer's storage is not infinite. Specifically, an int covers 32 bits (4 bytes), and thus can only represent at most 2^32 different numbers. int 'uses' its alloted space of 2^32 by dividing it evenly amongst positive and negative numbers, but negative numbers get one more (because the '0' is in the positive space). In other words, all numbers from -2^31 to +2^31-1, inclusive.
9876543210 is larger than that.
You're trying to turn that array of digits into an int and that is a dead end. Once you do that, you get wrong answers and there is no fixing this. your algorithm is wrong. You can figure this stuff out, and you should always do that with leetcode-style problems, by first carefully reading the assignment. The assignment covers the limits. It says how large these arrays can be, and I'm sure it says that they can be quite large; large enough that the number inside it is larger than 2^31-1. Probably larger than 2^63-1 (which a long can reach).
Then you know the algorithm you need to write can't involve 'turn it into an int first'. That's usually the point (many problems are trivial if small, but become interesting once you make things large).
The algorithm they want you to write must not involve any conversion whatsoever. Increment the array in place. This isn't hard (just think about it: without converting anything, how do you turn [1, 2, 3] into [1, 2, 4]? That should be simple. Then think about how to deal with [1, 9, 9]. Finally, think about how to deal with [9, 9, 9]. Then you've covered all the cases and you have your answer.
In continuation to the detailed explanation of rzwitserloot, in case you are interested in code for the problem.
class Solution {
public int[] plusOne(int[] digits) {
int size = digits.length;
int i=0;
for(i = size-1 ; i >= 0 ; i--){
if (digits[i] != 9) {
digits[i] += 1;
break;
} else {
digits[i] = 0;
}
}
if(i == -1) {
int[] newDigits = new int[size+1];
newDigits[0] = 1;
return newDigits;
}
return digits;
}
}
This is a pretty trivial task, but in some test cases the value is too high to represent even as long, so the best candidate is BigInteger.
public int[] plusOne(int[] digits) {
BigInteger val = BigInteger.ZERO;
for (int i = 0; i < digits.length; i++)
val = val.multiply(BigInteger.TEN).add(BigInteger.valueOf(digits[i]));
val = val.add(BigInteger.ONE);
String str = val.toString();
digits = str.length() == digits.length ? digits : new int[str.length()];
for (int i = 0; i < digits.length; i++)
digits[i] = str.charAt(i) - '0';
return digits;
}
P.S. Sure, you can do this without BigInteger.
public int[] plusOne(int[] digits) {
boolean carry = true;
for (int i = digits.length - 1; carry && i >= 0; i--) {
carry = digits[i] == 9;
digits[i] = carry ? 0 : digits[i] + 1;
}
if (carry) {
int[] tmp = new int[digits.length + 1];
tmp[0] = 1;
System.arraycopy(digits, 0, tmp, 1, digits.length);
digits = tmp;
}
return digits;
}
Think about a mileage counter in a car. How does it work?
Whenever a 9 turns around, it turns the number left to it too.
So for incrementing by one, you'd start from the right, increment by one and if you incremented it to a 10, set it to a 0 instead and continue with the next digit to the left. If you reached the leftmost digit and still didnt finish, add a 1 to the left and set everything else to 0.
Example:
8
9 <- incremented rightmost
10 <- 9 turned to a 10, leftmost digit reached, add a 1 to the left and set everything else to 0
...
18
19 <- incremented rightmost
20 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
108
109 <- incremented rightmost
110 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
998
999 <- incremented rightmost
1000 <- 9 turned to a 10, set to 0 instead, increment the next one to the left, turned to a 10 too, set to 0 instead, ...
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) {
int[] digits = new int[0];
for (int i = 0; i < 100; i++) {
digits = plusOne(digits);
System.out.println(IntStream.of(digits).mapToObj(Integer::toString).collect(Collectors.joining()));
}
}
public static int[] plusOne(int[] digits) {
boolean finished = false;
for (int i = digits.length - 1; !finished && i >= 0; i--) {
if (++digits[i] % 10 == 0) {
digits[i] = 0;
} else {
finished = true;
}
}
if (!finished) {
// not finished after exiting the loop: every digit was turned from a 9 to a 10 -> we need one digit more
// initialize a new array with a length of 1 more digit, set the leftmost (index 0) to 1 (everything else is 0 by default)
digits = new int[digits.length + 1];
digits[0] = 1;
}
return digits;
}
}
plus one in leetcode solve on dart language
class Solution {
List<int> plusOne(List<int> digits) {
for(int i=digits.length - 1; i>=0; i--){
if(digits[i] < 9){
++digits[i];
return digits;
}
digits[i]=0;
}
List<int> ans = List.filled(digits.length+1, 0);
ans[0]=1;
return ans;
}
}
Here is my solution:
Runtime: 0 ms, faster than 100.00% of Java online submissions for Plus One.
Memory Usage: 40.8 MB, less than 92.31% of Java online submissions for Plus One. for Plus One.
public int[] plusOne(int[] digits) {
for(int i=digits.length-1;i>=0;i--) {
if(digits[i]<9) {
digits[i]=digits[i]+1;
return digits;
}else {
digits[i]=0;
if(i==0) {
digits= new int[digits.length+1];
digits[0]=1;
}
}
}
return digits;
}
My solution:
Runtime: 0 ms, Memory Usage: 2.1 MB,
play.golang link: https://go.dev/play/p/Vm28BdaIi2x
// function to add one digit based on diff scenarios
func plusOne(digits []int) []int {
i := len(digits) - 1
// while the index is valid and the value at [i] ==
// 9 set it as 0 and move index to previous value
for i >= 0 && digits[i] == 9 {
digits[i] = 0
i--
}
if i < 0 {
//leveraging golang's simplicity with append internal method for array
return append([]int{1}, digits...)
} else {
digits[i]++
}
return digits
}

Down to Zero II

This is the question:
You are given Q queries. Each query consists of a single number N . You can perform any of the operations on in each move:
If we take 2 integers a and b where N=a*b (a ,b cannot be equal to 1), then we can change N=max(a,b)
Decrease the value of N by 1 .
Determine the minimum number of moves required to reduce the value of to .
Input Format
The first line contains the integer Q.
The next Q lines each contain an integer,N .
Output Format
Output Q lines. Each line containing the minimum number of moves required > to reduce the value of N to 0.
I have written the following code. This code is giving some wrong answers and also giving time limit exceed error . Can you tell what are the the mistakes present in my code ? where or what I am doing wrong here?
My code:
public static int downToZero(int n) {
// Write your code here
int count1=0;
int prev_i=0;
int prev_j=0;
int next1=0;
int next2=Integer.MAX_VALUE;
if (n==0){
return 0;
}
while(n!=0){
if(n==1){
count1++;
break;
}
next1=n-1;
outerloop:
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i*j==n){
if (prev_i ==j && prev_j==i){
break outerloop;
}
if (i !=j){
prev_i=i;
prev_j=j;
}
int max=Math.max(i,j);
if (max<next2){
next2=max;
}
}
}
}
n=Math.min(next1,next2);
count1++;
}
return count1;
}
This is part is coded for us:
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
int q = Integer.parseInt(bufferedReader.readLine().trim());
for (int qItr = 0; qItr < q; qItr++) {
int n = Integer.parseInt(bufferedReader.readLine().trim());
int result = Result.downToZero(n);
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
}
}
Ex: it is not working for number 7176 ....
To explore all solution tree and find globally optimal solution, we must choose the best result both from all possible divisor pairs and from solution(n-1)
My weird translation to Java (ideone) uses bottom-up dynamic programming to make execution faster.
We calculate solutions for values i from 1 to n, they are written into table[i].
At first we set result into 1 + best result for previous value (table[i-1]).
Then we factor N into all pairs of divisors and check whether using already calculated result for larger divisor table[d] gives better result.
Finally we write result into the table.
Note that we can calculate table once and use it for all Q queries.
class Ideone
{
public static int makezeroDP(int n){
int[] table = new int[n+1];
table[1] = 1; table[2] = 2; table[3] = 3;
int res;
for (int i = 4; i <= n; i++) {
res = 1 + table[i-1];
int a = 2;
while (a * a <= i) {
if (i % a == 0)
res = Math.min(res, 1 + table[i / a]);
a += 1;
}
table[i] = res;
}
return table[n];
}
public static void main (String[] args) throws java.lang.Exception
{
int n = 145;//999999;
System.out.println(makezeroDP(n));
}
}
Old part
Simple implementation (sorry, in Python) gives answer 7 for 7176
def makezero(n):
if n <= 3:
return n
result = 1 + makezero(n - 1)
t = 2
while t * t <= n:
if n % t == 0:
result = min(result, 1 + makezero(n // t))
t += 1
return result
In Python it's needed to set recursion limit or change algorithm. Now use memoization, as I wrote in comments).
t = [-i for i in range(1000001)]
def makezeroMemo(n):
if t[n] > 0:
return t[n]
if t[n-1] < 0:
res = 1 + makezeroMemo(n-1)
else:
res = 1 + t[n-1]
a = 2
while a * a <= n:
if n % a == 0:
res = min(res, 1 + makezeroMemo(n // a))
a += 1
t[n] = res
return res
Bottom-up table dynamic programming. No recursion.
def makezeroDP(n):
table = [0,1,2,3] + [0]*(n-3)
for i in range(4, n+1):
res = 1 + table[i-1]
a = 2
while a * a <= i:
if i % a == 0:
res = min(res, 1 + table[i // a])
a += 1
table[i] = res
return table[n]
We can construct the directed acyclic graph quickly with a sieve and
then compute shortest paths. No trial division needed.
Time and space usage is Θ(N log N).
n_max = 1000000
successors = [[n - 1] for n in range(n_max + 1)]
for a in range(2, n_max + 1):
for b in range(a, n_max // a + 1):
successors[a * b].append(b)
table = [0]
for n in range(1, n_max + 1):
table.append(min(table[s] for s in successors[n]) + 1)
print(table[7176])
Results:
7
EDIT:
The algorithm uses Greedy approach and doesn't return optimal results, it just simplifies OP's approach. For 7176 given as example, below algorithm returns 10, I can see a shorter chain of 7176 -> 104 -> 52 -> 13 -> 12 -> 4 -> 2 -> 1 -> 0 with 8 steps, and expected answer is 7.
Let's review your problem in simple terms.
If we take 2 integers a and b where N=a*b (a ,b cannot be equal to 1), then we can change N=max(a,b)
and
Determine the minimum number of moves required to reduce the value of to .
You're looking for 2 factors of N, a and b and, if you want the minimum number of moves, this means that your maximum at each step should be minimum. We know for a fact that this minimum is reached when factors are closest to N. Let me give you an example:
36 = 1 * 36 = 2 * 18 = 3 * 12 = 4 * 9 = 6 * 6
We know that sqrt(36) = 6 and you can see that the minimum of 2 factors you can get at this step is max(6, 6) = 6. Sure, 36 is 6 squared, let me take a number without special properties, 96, with its square root rounded down to nearest integer 9.
96 = 2 * 48 = 3 * 32 = 4 * 24 = 6 * 16 = 8 * 12
You can see that your minimum value for max(a, b) is max(8, 12) = 12, which is, again, attained when factors are closest to square root.
Now let's look at the code:
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i*j==n){
You can do this in one loop, knowing that n / i returns an integer, therefore you need to check if i * (n / i) == n. With the previous observation, we need to start at the square root, and go down, until we get to 1. If we got i and n / i as factors, we know that this pair is also the minimum you can get at this step. If no factors are found and you reach 1, which obviously is a factor of n, you have a prime number and you need to use the second instruction:
Decrease the value of N by 1 .
Note that if you go from sqrt(n) down to 1, looking for factors, if you find one, max(i, n / i) will be n / i.
Additionally, if n = 1, you take 1 step. If n = 2, you take 2 steps (2 -> 1). If n = 3, you take 3 steps (3 -> 2 -> 1). Therefore if n is 1, 2 or 3, you take n steps to go to 0. OK, less talking, more coding:
static int downToZero(int n) {
if (n == 1 || n == 2 || n == 3) return n;
int sqrt = (int) Math.sqrt(n);
for (int i = sqrt; i > 1; i--) {
if (n / i * i == n) {
return 1 + downToZero(n / i);
}
}
return 1 + downToZero(n - 1);
}
Notice that I'm stopping when i equals 2, I know that if I reach 1, it's a prime number and I need to go a step forward and look at n - 1.
However, I have tried to see the steps your algorithm and mine takes, so I've added a print statement each time n changes, and we both have the same succession: 7176, 92, 23, 22, 11, 10, 5, 4, 2, 1, which returns 10. Isn't that correct?
So, I found a solution which is working for all the test cases -
static final int LIMIT = 1_000_000;
static int[] solutions = buildSolutions();
public static int downToZero(int n) {
// Write your code here
return solutions[n];
}
static int[] buildSolutions() {
int[] solutions = new int[LIMIT + 1];
for (int i = 1; i < solutions.length; i++) {
solutions[i] = solutions[i - 1] + 1;
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
solutions[i] = Math.min(solutions[i], solutions[i / j] + 1);
}
}
}
return solutions;
}
}

Java:Three digit Sum - Find out all the numbers between 1 and 999 where the sum of 1st digit and 2nd digit is equal to 3rd digit

Problem statement: Three digit sum - Find all the numbers between 1 and 999 where the sum of the 1st digit and the 2nd digit is equal to the 3rd digit.
Examples:
123 : 1+2 = 3
246 : 2+4 = 6
Java:
public class AssignmentFive {
public static void main(String[] args) {
int i=1;
int valuetwo;
int n=1;
int sum = 0;
int valuethree;
int valueone = 0;
String Numbers = "";
for (i = 1; i <= 999; i++) {
n = i;
while (n > 1) {
valueone = n % 10;/*To get the ones place digit*/
n = n / 10;
valuetwo = n % 10;/*To get the tens place digit*/
n = n / 10;
valuethree = n;/*To get the hundreds place digit*/
sum = valuethree + valuetwo;/*adding the hundreds place and
tens place*/
}
/*Checking if the ones place digit is equal to the sum and then print
the values in a string format*/
if (sum == valueone) {
Numbers = Numbers + n + " ";
System.out.println(Numbers);
}
}
}
}
I got my result :
1
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
10000000001
100000000011
1000000000111
10000000001111
100000000011111
1000000000111111
10000000001111111
100000000011111111
1000000000111111111
Process finished with exit code 0
The result is not showing the actual result like it should be which should show values like: 123, 246 (Please refer to the problem statement above.)
Please let me know what seems to be the issue with the code and how to tweak it.
Don't know what you're trying to do with that while loop, or why you are building up a space-separated string of numbers.
Your code should be something like:
for (int n = 1; n <= 999; n++) {
int digit1 = // for you to write code here
int digit2 = // for you to write code here
int digit3 = // for you to write code here
if (digit1 + digit2 == digit3) {
// print n here
}
}
So basically your question is how to calculate the numbers, right?
My first hint for you would be how to get the first, second and third value from a 2 or 3 digit number.
For example for 3 digits you can do int hundretDigit = (n - (n % 100)) % 100. Of course this is really inefficient. But just get code working before optimizing it ;)
Just think about a way to get the "ten-digit" (2nd number). Then you add them and if they equal the third one you write System.out.println(<number>);
EDIT:
For 2 digit numbers I will give you the code:
if(i >= 10 && i <= 99) {
int leftDigit = (i - (i % 10)) / 10;
if(leftDigit == (i % 10)) {
//Left digit equals right digit (for example 33 => 3 = 3
System.out.println(i);
}
}
Try again and edit your source code. If you have more questions I will edit my (this) answer to give you a little bit more help if you need!

Terminated due to timeout error [duplicate]

I am working on a program that takes an integer and finds the number of combinations of consecutive sums that the integer has:
The number 13 can be expressed as a sum of consecutive positive
integers 6 + 7. Fourteen can be expressed as 2 + 3 + 4 + 5, also a sum
of consecutive positive integers. Some numbers can be expressed as a
sum of consecutive positive integers in more than one way. For
example, 25 is 12 + 13 and is also 3 + 4 + 5 + 6 + 7.
I researched and read that it's the number of odd factors minus one. So I wrote a program that finds the number of odd factors and my answer is still wrong in certain cases. Any insight?
Code seems to work fine but there is a crash due to Timeout which is probably due to optimization error.
The constraints for possible input size is
1 to 10^(12)
The code below is copied from alfasin's answer below:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
static long consecutive(long num) {
while (num % 2 == 0) num /= 2;
return consecutiveHelper(num);
}
public static long consecutiveHelper(long num) {
return LongStream.rangeClosed(3, (num / 2)).parallel().filter(x -> x % 2 != 0).map(fn -> (num % fn == 0) ? 1 : 0).sum();
}
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
final String fileName = System.getenv("OUTPUT_PATH");
BufferedWriter bw = null;
if (fileName != null) {
bw = new BufferedWriter(new FileWriter(fileName));
}
else {
bw = new BufferedWriter(new OutputStreamWriter(System.out));
}
int res;
long num;
num = Long.parseLong(in.nextLine().trim());
res = consecutive(num);
bw.write(String.valueOf(res));
bw.newLine();
bw.close();
}
}
This is what i currently have
As the post i answered to was duplicate, I copied my answer here as well.Let's try to find a pseudo-optimized method to resolve your problem :
What you need to do is to decompose your number in prime factors.
For example, if you take 1200 :
1200 = 2*2*2*2*3*5*5 = 1 * 2^4 * 3^1 * 5^2
You can then analyze how you could get odd factors with those prime factors. A quick analyze will tell you that :
odd * odd = odd
odd * even = even
even * even = even
With that in mind, let's find all the factors we get with odd * odd :
1 * 1 = 1
3 * 1 = 3
5 * 1 = 5
5 * 3 = 15
5 * 5 = 25
5 * 5 * 3 = 75
A quick way to find these combinations without writing them all is the "plus 1 method" : add 1 to the number of occurences of each prime odd factor, and multiply them together :
We found that 1200 = 1 * 2^4 * 3^1 * 5^2, so we can do :
("number of 3" + 1) ("number of 5" + 1) = (1 + 1) ( 2 + 1) = 6
There are 6 odd factors for the number 1200, and as you stated, remove 1 from that number to get the number of combinations of consecutive sums that 1200 has :
6 - 1 = 5 <-- woohoo ! finally got the result !
Now, let's look at the code. What we want to have is a Map, the keys being the prime factors and the values being the number of their occurences :
/*
If number is odd,
find the number in the keys and add 1 to its value.
If the number is not in the keys, add it with value = 1.
*/
public static void addValue(Map<Integer, Integer> factors, int i) {
if(i % 2 != 0) {
int count = factors.containsKey(i) ? factors.get(i) : 0;
factors.put(i, ++count);
}
}
/*
Classic algorithm to find prime numbers
*/
public static Map<Integer, Integer> oddPrimeFactors(int number) {
int n = number;
Map<Integer, Integer> factors = new HashMap<>();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
addValue(factors, i);
n /= i;
}
}
if(n > 1) addValue(factors, n);
return factors;
}
With that, let's try to print what the map contains for number 1200 :
public static void main(String[] args) {
int n = 1200;
System.out.println(oddPrimeFactors(n));
}
$n : {3=1, 5=2}
Good ! Now let's finish the program with the method we developed before :
public static int combinations = 1;
public static void main(String[] args) {
int n = 1200;
oddPrimeFactors(n).forEach((key, value) -> combinations *= (value + 1));
combinations--;
System.out.println(combinations);
}
$combinations = 5
Finished ! feel free to ask if you did not understand something !
Note : I tried my program with the max value Integer can handle and it took less than one second for my program to proceed, which seems pretty fast to me. It could probably be faster though, it's up to you to find the most optimized version of this code !
Here are the optimizations that we discussed in the comments section, see comments as markers:
static int consecutive(long num) {
while (num % 2 == 0) num /= 2; // 1st opt.
return consecutiveHelper(num)-1;
}
public static int consecutiveHelper(long num) {
long factorNumber = 1;
int count = 0;
while(factorNumber <= num / 2) { // 2nd opt.
if(num % factorNumber == 0) {
count++;
}
factorNumber += 2; // 3rd opt.
}
if (num % 2 != 0) {
count++;
}
return count;
}
UPDATE
I managed to reduce ~50% runtime for big-numbers (10^12) by using Java 8 Stream interface and running in parallel:
static long consecutive(long num) {
while (num % 2 == 0) num /= 2;
return consecutiveHelper(num);
}
public static long consecutiveHelper(long num) {
return LongStream
.rangeClosed(3, (num / 2))
.parallel()
.filter(x -> x % 2 != 0)
.map(fn -> (num % fn == 0) ? 1 : 0)
.sum();
}
That said, parallel will be more expensive when you're dealing with smaller numbers. If you want your answer to be optimal you should use both methods: for smaller numbers use the first and for large numbers use the latter.

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