This is one of the questions that I faced in competitive programming.
Ques) You have an input String which is in binary format 11100 and you need to count number of steps in which number will be zero. If number is odd -> subtract it by 1, if even -> divide it by 2.
For example
28 -> 28/2
14 -> 14/2
7 -> 7-1
6 -> 6/2
3 -> 3-1
2 -> 2/2
1-> 1-1
0 -> STOP
Number of steps =7
I came up with the following solutions
public int solution(String S) {
// write your code in Java SE 8
String parsableString = cleanString(S);
int integer = Integer.parseInt(S, 2);
return stepCounter(integer);
}
private static String cleanString(String S){
int i = 0;
while (i < S.length() && S.charAt(i) == '0')
i++;
StringBuffer sb = new StringBuffer(S);
sb.replace(0,i,"");
return sb.toString();
}
private static int stepCounter(int integer) {
int counter = 0;
while (integer > 0) {
if (integer == 0)
break;
else {
counter++;
if (integer % 2 == 0)
integer = integer / 2;
else
integer--;
}
}
return counter;
}
The solution to this question looks quite simple and straightforward, however the performance evaluation of this code got me a big ZERO. My initial impressions were that converting the string to int was a bottleneck but failed to find a better solution for this. Can anybody please point out to me the bottlenecks of this code and where it can be significantly improved ?
If a binary number is odd, the last (least significant) digit must be 1, so subtracting 1 is just changing the last digit from 1 to 0 (which, importantly, makes the number even).
If a binary number is even, the last digit must be 0, and dividing by zero can be accomplished by simply removing that last 0 entirely. (Just like in base ten, the number 10 can be divided by ten by taking away the last 0, leaving 1.)
So the number of steps is two steps for every 1 digit, and one step for every 0 digit -- minus 1, because when you get to the last 0, you don't divide by 2 any more, you just stop.
Here's a simple JavaScript (instead of Java) solution:
let n = '11100';
n.length + n.replace(/0/g, '').length - 1;
With just a little more work, this can deal with leading zeros '0011100' properly too, if that were needed.
Number of times you need to subtract is the number of one bits which is Integer.bitCount(). Number of times you need to divide is the position of most-significant bit which is Integer.SIZE (32, total number of bits in integer) minus Integer.numberOfLeadingZeros() minus one (you don't need to divide 1). For zero input I assume, the result should be zero. So we have
int numberOfOperations = integer == 0 ? 0 : Integer.bitCount(integer) +
Integer.SIZE - Integer.numberOfLeadingZeros(integer) - 1;
As per the given condition, we are dividing the number by 2 if it is even which is equivalent to remove the LSB, again if number is odd we are subtracting 1 and making it an even which is equivalent to unset the set bit (changing 1 to 0). Analyzing the above process we can say that the total number of steps required will be the sum of (number of bits i.e. (log2(n) +1)) and number of set bits - 1(last 0 need not to be removed).
C++ code:
result = __builtin_popcount(n) + log2(n) + 1 - 1;
result = __builtin_popcount(n) + log2(n);
Related
Not sure if anyone can explain this to me or help me.
I have a 15 Digit Number of which I want to multiply each even number by 2 unless the even number is greater than 9. If it is this needs to be subtracted by 9 to give me an integer that again I can multiply by 2. Once I have all the even numbers multiplied by 2 i need to add them all together with the odd numbers.
Does that make sense.
UPDATE ***
so i have a number say 49209999856459. for that number I am looking to get the even integer so for example the first even one would be 4 then the second would be 2 and so on.
If one of those even numbers are multiplied by 2 then it might be above 9 so I want to subtract 9 to then use the remainder as the even number in its place.
SO !!!
Multiply by 2 the value of each even digit starting from index 0 and then each even index. In each case, if the resulting value is greater than 9, subtract 9 from it (which reduces larger values to a single digit). Leave the values of the digits at the odd indexes unchanged.
public String calculateCheckNumber()
String firstFifteen = longNumber.substring(0,15) ;
int i, checkSum = 0, totalSum = 0;
for (i = 0; i<firstFifteen.length(); i += 2) {
while (i < 9)
i *= 2;
if (i > 9)
i -= 9 ;
}
Was one option I was trying but it honestly I cant seem to get my head around it.
Any Help would be greatly appreciated.
Well, here is one approach. This uses the ternary (?:) operator to condense the operations. Edited base on clarification from the OP. The example you gave is actually a 14 digit string. But the following will work with any number of digits if they start out in a string. If you have a long value, then you can create the character array using:
long v = 49209999856459L;
char[] d = Long.toString(v).toCharArray();
Here is the main algorithm.
String s = "49209999856459";
int sum = 0;
char[] d = s.toCharArray();
for (int i = 0; i < d.length; i++) {
int v = d[i] - '0';
// The even digit will only be greater than 9 after
// doubling if it is >= 5 before.
sum += ((i % 2) == 1) ? v : (v >= 5) ? v+v-9 : v+v;
}
System.out.println(sum);
Prints
86
Can someone explain this code line by line. I just started to learn how to code and I'm learning java right now,but I'm having hard time how this function executes. What does new int[10]; really do? and I don't really get the difference or how repeatedDigits[index] part is used differently from the repeatedDigits[remainder] part.
Write a function that counts the repeated digits in the integer x.
For * example: if x is 999, then your function must print back that 9 occurs 3 * times. Another example, if the integer x is 992121, then your function * must print back that 9 occurs 2 times, 2 occurs 2 times and 1 occurs 2 * times. This was a guideline for the function.
public static void countRepeatedDigitsInANumber(int x) {
int[] repeatedDigits = new int[10];
while (x > 0) {
int remainder = x % 10;
x = x / 10;
repeatedDigits[remainder] = repeatedDigits[remainder] + 1;
}
int index = 0;
while (index < 10) {
if (repeatedDigits[index] != 0)
System.out.println("The digit " + index + " occurs " +
repeatedDigits[index]);
index++;
}
}
This is a code that compiles. I'm just posting this because I'm having hard time to understand. I would realy appreciate if someone could give any suggestion to learn java quickly as well!
What does new int[10];
It creates a new array of size 10 that can hold int values. All of the values in the array will be initialized to 0 (this is just how Java handles int primitives).
In this case, it looks like this array is being used to store the number of times that the digit corresponding to its index has been seen.
Hmm, that was confusing to type, and probably even more confusing to read, so let me use an example. For the input 992121, you'd expect the repeatedDigits array to look like this when the program is done:
[0, 2, 1, 0, 0, 0, 0, 0, 0, 2]
i.e. Two 1s, one 2, and two 9s
while (x > 0) {
This starts a loop that will keep going until x is equal to (or smaller than, but that shouldn't happen) zero.
int remainder = x % 10;
This essentially "captures" the right-most digit of the number using modular arithmetic. It divides the number by 10, and any remainder is going to be what's in the "ones place" (i.e. the right-most digit).
x = x / 10;
This shifts digits to the right by one, and throws away the right-most digit (since you've already captured it).
repeatedDigits[remainder] = repeatedDigits[remainder] + 1
This just increments the value in the array at the appropriate location. For example, if you just pushed a 9 off the right end of the number, this will increment the value in repeatedDigits[9] so you know that you just saw an additional 9.
int index = 0;
while (index < 10) {
We're about to do some looping! There are (in my opinion) better ways to do this, but this works just as well. Basically, you want index to start at 0, and loop all the way up to 9, but stop when you get to 10.
if (repeatedDigits[index] != 0)
If the value at a given location in the repeatedDigits array is not zero, then...
System.out.println("The digit " + index + " occurs " + repeatedDigits[index]);
... print it out!
index++;
And finally, increment index so we can check the next number. This is exactly the same as index = index + 1.
Welcome to SO and the beautiful world of Java! I've attached hyperlinks all throughout my answer that could possibly help you out.
int[] repeatedDigits = new int[10];
The above line of code is creating an array with 10 elements, from index: 0 to index: 9.
int remainder = x % 10;
The above line of code is calculating the remainder once 'x' has been divided by 10. For example, if 'x = 9192' then it would be dividing '9192 / 10 = 919.2' And taking the remainder. Which in this case is the '2'. Notice how it's actually looking at the number in reverse? So a number like '9192' is actually being processed as '2919'.
x = x / 10;
The above line of code is dividing the number down by 10- since it's integer division it drops all decimal values. Since we have already calculated the last number. So our '9192' is now just '919'.
repeatedDigits[remainder] = repeatedDigits[remainder] + 1;
The above line of code is going to the index of the array of the remainder value that we stored earlier. Remember how our remainder was '2'? It's not going to index: 2 in our array and adding 1 to it's value- which was originally 0. So now our array at index: 2 has the value: 1. Meaning the number 2 was repeated 1 time.
What I've laid out above is just 1 iteration of the while loop that the top half of your code is in. So get a piece of paper and redo everything I did above with the remaining number '919'.
Once you're finished you should notice that your array looks something like this:
index 0: 0
index 1: 1
index 2: 1
index 3: 0
index 4 to 8: 0
index 9: 2
This means that '1' came once. '2' came once. and '9' came twice.
As for advice on learning Java? Read a lot. Google every little question you have, and if you don't understand how something is working get a piece of paper and write it out.
int[] repeatedDigits = new int[10];
//create an array of integers of size 10
while (x > 0) {
//while the integer provided is greater than 0
int remainder = x % 10;
//gets the smallest value digit in a base ten system. 101%10 =1
x = x / 10;
//in base ten this reduces the size of the number by a tens place. 101/10 =10 as 10 can be fully divided into 101 10 times. You've dropped the last digit of the number in this way. This is what will allow you to exit the while loop, as eventually x will be equal to 0.
repeatedDigits[remainder] = repeatedDigits[remainder] + 1;
remainder here can be between 0-9. This is because remainder is the remainder of dividing the provided integer by 10. You can't divide a number greater than 0 by ten and have a value less than zero or greater than 9.
The array you created has indexes 0-9, as it is ten spaces long (0,1,2,3,4,5,6,7,8,9). You are assigning the value of the index of repeated Digits that corresponds to your remainder to whatever it was previously plus 1.
What this means is you have found that the last digit in the number is equal to some value X. X must be between 0-9. As you have an array with indexes between 0-9 you get the value associated with repeatedDigits[X], add one to it as you have found another value of X, and set repeatedDigits[X]'s value equal to what is was before you found this new X plus one.
}
int index = 0;
You start at the first value of an array (0)
while (index < 10) {
Go through the values of the array from 0 to 9
if (repeatedDigits[index] != 0)
if the value of the array repeatedDigits at index is not 0. This is the same as saying if there was a value of index found in the input number.
System.out.println("The digit " + index + " occurs " +
repeatedDigits[index]);
index is the number we looked at. The count of how many times it occurred is stored at repeatedDigits[index]. We are printing the value and how many times it occurred.
index++;
Increase the index, examining the next index value.
}
}
Let me see if I can clear a few things up for you. My first suggestion is to format your code so that the lines within loops are indented:
public static void countRepeatedDigitsInANumber(int x) {
int[] repeatedDigits = new int[10];
while (x > 0) {
int remainder = x % 10;
x = x / 10;
repeatedDigits[remainder] = repeatedDigits[remainder] + 1;
}
int index = 0;
while (index < 10) {
if (repeatedDigits[index] != 0)
System.out.println("The digit " + index + " occurs " + repeatedDigits[index]);
index++;
}
}
}
This helps us to see the structure of the program. We can now see that the program runs as follows:
Define a new int array: int[] repeatedDigits = new int[10];
Run a while loop: while (x > 0) { ... }
Define an int variable: int index = 0;
Run a second while containing an if statement: while (index < 10) { if ( ... ) { ... } }
I'll try to explain each of the four pieces one at a time.
First we define our int array. new int[10] defines an array with ten spots in it, each of which can hold an integer. You can think of this like ten boxes next to each other, each labeled with an index. This array will be used to keep track of how many times we've seen each integer. repeatedDigits[0] will hold the number of times we've seen a 0 digit in our number; repeatedDigits[6] will hold the number of times we've seen a 6 digit, and so on.
Here's the heart of the program. We're going to break down the number, one digit at a time, and for each digit, we add one to the spot in the array used to keep track of how many times we've seen that digit. This line gets us the rightmost digit in our number: int remainder = x % 10;. % is called the modulo operator, and you can search for that to learn more about it. With the input 992121, this will assign remainder to 1.
The next line uses integer division to remove that last digit from the number, so that the next time through the loop we get the next digit. if x = 992121 then after x = x / 10, x will equal 99212.
Finally, we add one to the spot in the repeatedDigits array corresponding to the digit we saw. So in our example, remainder = 1, so we add 1 to the repeatedDigits[1] spot. This line takes advantage of the fact that an uninitialized int defaults to 0.
We've reached the end of the while loop, so we check the condition, and find that x > 0, so we run the loop again. We repeat this for every digit in the input number`.
The hard work is now done; the rest of the program is there to print out the results.
We assign index to 0. The next while loop will increment this variable from 0 to 9, printing the value of the repeatedDigits array for each digit.
We run the loop from index = 0 to index = 9. For each value, we check to see if we saw that digit in our input number (that's the if statement). We check the value in repeatedDigits[index] to see if it doesn't equal 0. If so, then we must have incremented it in the previous loop, so we know that digit appeared at least once in the original input. In that case, we print a line to the console using System.out.println. Then we increment index and start the loop again.
Please let me know if you have any questions, and good luck!
I'm trying to solve the following problem from the section Bit Manipulation at the Hacker Rank site using new features of Java 8 such as Streams.
The problem description:
Given an integer, n, find each x such that:
0 <= x <= n
n + x = n ^ x
where ^ denotes the bitwise XOR operator. Then print an integer denoting the total number of x's satisfying the criteria above.
Constraints
0 <= n <= 1015
Sample Input: 5
Sample Output: 2
Explanation:
For n = 5, the x values 0 and 2 satisfy the conditions:
5 + 0 = 5 ^ 0 = 5
5 + 2 = 5 ^ 2 = 7
Thus, we print 2 as our answer.
Sample Input: 10
Sample Output: 4
Explanation:
For n = 10, the x values 0, 1, 4, and 5 satisfy the conditions:
10 + 0 = 10 ^ 0 = 10
10 + 1 = 10 ^ 1 = 11
10 + 4 = 10 ^ 4 = 14
10 + 5 = 10 ^ 5 = 15
Thus, we print 4 as our answer.
My code is as follows:
public class SumVsXor
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long count = LongStream.rangeClosed(0, n)
.filter(k -> k + n == (k ^ n))
.count();
System.out.println(count);
}
}
The problem is this code doesn't pass all the test cases.
It works for small values of n, but for large values such as 1000000000000000 it fails due to timeout.
I wonder whether LongStream can't handle Streams with that many elements.
The problem with your code is that it is very inefficient. For the case of n==1000000000000000, your Stream pipeline is performing 1,000,000,000,000,000 addition and XOR operations, which takes a long time. Testing for each number between 0 and n whether n + x == n ^ x would take a long time even if you use a for loop instead of Streams.
Instead of checking all the numbers between 0 and n, you should try to figure out a better way to calculate the required total number of x's. That fact that this problem appears under a "Bit Manipulation" section should give you a hint
to look into the bits of numbers that satisfy n + x == n ^ x.
Let's consider the case of n==1000000000000000. The binary representation of that large number is
0000000000000011100011010111111010100100110001101000000000000000
=== == = ====== = = = == == =
--- - - - - -- -- --- - ---------------
~~~~~~~~~~~~~~
In order for n + x to be equal to n ^ x, x must have a 0 value in all the bits corresponding with the 1 bits of n (marked with = above), and either 0 or 1 value in the bits corresponding with the 0 bits of n (marked with - above). This doesn't include the leading 0s (marked with ~ above), since x must be <= n, so any leading 0s in n must also have a 0 value in x.
This means that the total number of x's for which n + x == n ^ x is 2the number of 0s in n, not including leading 0s.
In the case of n = 1000000000000000, there are 30 such 0 bits, so the total number of x's that satisfy the requirement is 230.
Here's one way to compute the total number of x's :
long n = 1000000000000000L;
int zeroBitsCount = 0;
while (n > 0) {
if (n % 2 == 0) {
zeroBitsCount++; // counts the number of non-leading 0 bits
}
n = n >> 1; // divide n by 2 in order to examine the next bit in the next iteration
}
long total = 1L << zeroBitsCount; // the total is 2^(the 0 bits count)
I came to the same result, but via a different explanation, so thought I might post it here.
Eran's answer got to the same conclusion that I did : to modify the zeroes in the binary representation of the initial number - that is pretty straightforward.
Let's suppose our number is
101010100
so it has 5 zeroes.
you need all the possible combinations of:
a single zero
two zeroes
three zeroes
four zeroes
five zeroes
that is actually :
comb(1,5) + comb(2,5) + comb(3,5) + comb(4,5) + comb (5,5)
that is a well known formula being equal to:
pow(2,n) // where n is five in our case
from there the solution is obvious...
This is a simple question if you know little bit about XOR. I don't know much about java. But I can explain in python.
1.First convert the number to binary.
2.Count the number of zeros in that binary number.
3.print 2 ^ (number of zeros) and that's it.
Here is my python code.
n = int(input())
sum = 0
if n!=0:
n=str(bin(n))
for i in range(len(n)):
if n[i]=='0':
sum = sum + 1
print(2**(sum-1))
else: print(1)
The reason to decrement the sum by 1 is, in python it convert the number to the binary as this format. e.g: 0b'10101.
public static void main (String[] args) {
Scanner in = new Scanner (System.in);
long n = in.nextLong();
long count = 1L << (64-Long.bitCount(n)-Long.numberOfLeadingZeros(n));
System.out.println(count);
}
I have a question where I have to add numbers from 1 to N which have their set bits as 2. Like for N = 5 we should get value 8, as number 3 and 5 have 2 bits set to one. I am implementing the same in java. I am getting the o/p correct for int value but when it comes to the long values, either it's taking a lot of time or freezing, and when I submit the same on code judge sites, it's giving run time exceeded message. Please guide me how may I optimise my code to run it faster, thanks :)
public static void main(String[] args)
{
long n = 1000000L;
long sum = 0;
long start = System.currentTimeMillis();
for(long i = 1L ; i <= n ; i++)
{
if(Long.bitCount(i) == 2)
{
sum += i;
}
}
long end = System.currentTimeMillis();
System.out.println(sum);
System.out.println("time="+(end-start));
}
As #hbejgel notes, there is no point in looping over all numbers and checking their bit count. You can simply construct numbers with 2 bits and add them up.
You can construct a number with 2 bits by picking two different bit positions in the long, the "higher" bit and the "lower" bit":
long i = (1 << higher) + (1 << lower);
So, you can simply loop over all such numbers, until the value you have constructed exceeds your limit:
long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
for (int lower = 0; lower < higher; ++lower) {
long i = (1 << higher) + (1 << lower);
if (i <= n) {
sum += i;
}
if (i >= n) break outer;
}
}
Let's say we know the closest number, x, equal to or lower than N with 2 set bits, then we can use the formula for power series to quickly sum all positions of the two set bits, for example, if x = b11000, we sum
4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x
where S(n) = 2 * (1 - 2^n) / (1 - 2)
= 2 + 2^2 + 2^3 ... + 2^n
With numbers encoded 2 out of 5, exactly two bits are set in every one-digit number. The sum is 45, with the exception of N×(N-1)/2 for 0≤N<9.
I think the question is supposed to discover the pattern.
Fast forward. Given a number N, you can tell the largest number
should count by bitmask from the first two bits are set. So you have
a smaller number M
Skip to next counted number Given any number with two bit set, next
largest number is the shift the second bit by one, until underflow.
Skip to next order When underflow happens on set two, shift the
highest bit by one and also the bit on it's right.
You don't really need a loop on N, but the bits it have.
Next question: can you answer a large number? which N >100,000,000
Next Next question: can you answer the same question for X bits when X>2
I have a group of numbers 0 to 9 => {0 .. 9}, but another group that represent each amount of {0 .. 9} we have, for example:
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
5 => 6
6 => 7
7 => 8
8 => 9
9 => 1
The lowest value that we cannot represent with those groups is 99. They are digits to represent a number, for example if we only have:
2 => 2
7 => 1
The lowest value should be 0 or 1, and the possibilities are, 2, 7, 22, 27, 72, 227, 272, 722.
I am doing an algorithym in java to calculate the lowest value that we cannot represent, but I even do not very well how to do it, and I need a little or big help.
Thanks.
You should decompose your problem.
Global algorithm
IMO, you should start at n = 0, and go up. For each value of n, check if the sequence of digits needed to represent it is allowed. As soon as you can't, n is your answer.
Smaller part
The new problem is to verify if the sequence of digits for a given number is allowed. That does not seem very difficult. You seem to deal with base 10 numbers only I guess:
decompose your number in base 10 digits
count the number of occurrences of each digit in your number
compare with the quantity available of that digit
if there are not enough, you're done, the number can't be represented
if there are enough, keep going with the other digits
Example implementation of the main algo. The argument nbAllowed would be a 10-sized array containing the quantity available of each digit. Ex: nbAllowed[2] is the number of times that the digit '2' is allowed to be used.
public static int smallestNonRepresentable(int[] nbAllowed) {
int n=0;
while (isRepresentable(n, nbAllowed)) {
n++;
}
return n;
}
Example implementation of the subroutine. This methods returns whether n is representable depending on the quantity available for each digit.
private static boolean isRepresentable(int n, int[] nbAllowed) {
int[] digitCount = getDigitCount(n);
// check if each digit is available enough times
for (int d = 0; d < nbAllowed.length; d++) {
if (nbAllowed[d] < digitCount[d]) {
return false; // not enough d digits to represent n
}
}
return true; // enough of all digits
}
Example implementation of how to count the number of occurrences of each digit in a number n. This method returns a 10-sized array containing the number of occurrences of each digit in n. Ex: digitCount[2] is the number of times that the digit '2' appears in the decimal representation of n.
private static int[] getDigitCount(int n) {
int[] digitCount = new int[10]; // 10 distinct digits
Arrays.fill(digitCount, 0); // start at 0 occurrence for each digit
// special case 0
if (n == 0) {
digitCount[0] = 1; // 1 occurrence for digit '0'
return digitCount;
}
// fill digitCount with the number of occurrences of each digit in n
int digit;
while(n > 0) {
digit = n % 10; // current last digit of n
digitCount[digit]++; // increments the number of occurrences for that digit
n /= 10; // shifts the decimal number n to the right (last digit disappears)
}
return digitCount;
}
The problem can be solved by not applying brute-force. There are four cases to distinguish in the given order, which means if we evaluate case 3, case 1 and 2 did not apply:
There is at least one digit with an amount of zero: then the smallest of those digits is not representable.
The set of digits with the smallest available amount does not contain the digit zero: now we know the amount is greater than zero and hence repeating the smallest of those digits one more time than available digits is the smallest non representable number.
The set of digits with the smallest available amount has a size of one: now we know it has to be the digit zero having an amount greater than zero. And we know the next greater digit, the one is available, due to passed through case 1. Hence the number composed of a leading 1 followed by amount many zeros is the smallest non representable number.
We know the set of digits with the smallest available amount contains the digit zero and at least one more digit: hence repeating the second smallest digit of this set one more time than available digits is the smallest non representable number.
Expressed in terms of a Java program the main algorithm looks like this:
private static final List<Integer> DIGIT_POOL =
Arrays.asList(2, 1, 3, 4, 5, 6, 7, 8, 9, 1);
public static void main(String[] args) {
Map<Integer, List<Integer>> amountToDigits = mapToDigits(DIGIT_POOL);
String number;
int amount = amountToDigits.keySet().iterator().next();
List<Integer> digits = amountToDigits.get(amount);
if (amount == 0) {
number = number(digits.get(0), 1);
} else if (!digits.contains(0)) {
number = number(digits.get(0), amount + 1);
} else if (digits.size() == 1) {
number = paddedWithZero(1, amount + 2);
} else {
number = number(digits.get(1), amount + 1);
}
System.out.println(number);
}
private static SortedMap<Integer, List<Integer>> mapToDigits(List<Integer> digitAmounts) {
SortedMap<Integer, List<Integer>> amountToDigits = new TreeMap<>();
for (int digit = 0; digit <= 9; digit++) {
int amount = digitAmounts.get(digit);
List<Integer> digits = amountToDigits.get(amount);
if (digits == null) {
digits = new ArrayList<>();
amountToDigits.put(amount, digits);
}
digits.add(digit);
}
return amountToDigits;
}
Constructing the resulting non representable number requires the following helper methods:
private static String paddedWithZero(Integer digit, int length) {
char[] letters = letters(0, length);
letters[0] = digit.toString().charAt(0);
return new String(letters);
}
private static String number(Integer digit, int length) {
return new String(letters(digit, length));
}
private static char[] letters(Integer digit, int length) {
char[] letters = new char[length];
Arrays.fill(letters, digit.toString().charAt(0));
return letters;
}
The total complexity of the algorithms is the sum of:
mapping n digits to their amounts: O(n)
distinguishing between four cases: O(1)
constructing a number of lenght m + 1, where m is the smallest amount of available digits: O(m)
Hence the total complexity is O(max(n, m)) which is linear. This solution works pretty fast for very large amounts (1k and greater) of given digits.
When you're going from the lowest point, it's usually prudent to start at 0. So we'll need some sort of loop, and because we don't know how many times we'll look, we'll implement a while loop.
boolean numberFound = false;
while(!numberFound) {
// Loops while a number has not been found.
}
We also need to keep track of our current number, so we'll declare a pointer p.
int p = 0;
boolean numberFound = false;
while(!numberFound) {
}
Now, let's assume you've got all these values in an array. So 1 is in position 0, 2 is in position 1 etc. You need to get the first value of p. Now, for any value of p between 9 and 0 inclusively, we can just grab the number of occurrences, so we do something like:
if(p <= 9 && p >= 0) {
// Get the number of occurrences.
int numberOfDigits = digits[p] // Digits is your array as described above.
if(numberOfDigits == 0) {
// You only need one digit to represent this number.
// If you don't have one digit, you've just found a number that works.
numberFound = true;
}
}
Next, you'll need to deal with numbers larger than 9. Because this has more than one digit, you'll need to do this in stages:
First, convert the Integer into a String.
Next, cycle through each character in that String.
Parse that character back to an integer, and grab the value from the array.
Get the number of times that character occurs in a string.
If the value in the array is less than the number of times that value occurs..
You've found a number.
Else, keep looping.
Good luck with the last part of the solution. As a general rule, when it looks like someone hasn't made much of an effort with a problem, I don't provide the entire solution.
My understanding is the same as Joffrey's algo.
Write a method like:
public boolean checkIfInGroup(int value) {
...
}
then you can create a loop in your outer method:
int n=0;
while (checkIfInGroup(n)) {
n++;
}
return n;
The challenge would be how to optimize the checkIfInGroup() method.
If I understood you correctly, you have one Array with numbers from 0 - 9 and another one with the same numbers in a different order. You want to know, which number is the one below the smallest displayable. So, if I understood you correctly, it should always be -1, because, if you have numbers from 0 - 9, 0 is the lowest displayable number, so -1 is the one beneath that. Could I help?