Find middle digit in an integer in Java - java

I have an integer in java "1234567" and my program finds middle digit in a set of integer, is there more optimized way than below code?. Recently asked in java interview.
What I have done is first find no of digits, first, last and middle indexes. Then find middle digit again iterating on same integer. Please advice some optimization.
int a1 = 1234567;
int a = a1;
// calculate length
int noOfDigits = 0;
while(a!=0)
{
a = a/10;
noOfDigits++;
}
int first = 0;
int last = noOfDigits-1;
int middle = (first+last)/2;
boolean midExists = ((a1%2)==1);
System.out.println(" digits: "+a1);
System.out.println(" no of digits "+noOfDigits);
System.out.println(" first "+first);
System.out.println(" last " + last);
if(midExists)
{
System.out.println(" middle " + middle);
int i = last;
int middleDigit = 0;
a = a1;
while(i != middle)
{
a = (a / 10);
middleDigit = (a%10);
i--;
}
System.out.println("middle digit: " + middleDigit);
}
else
System.out.println(" Mid not Exists.. ");
Program Output:
digits: 1234567
no of digits 7
first 0
last 6
middle 3
middle digit: 4

You can also do this in one pass. Idea is that first store the integer in the another variable. Then move two digits to the left in one integer while only one digit in the another one.
int a1 = 1234567;
int a2 = a1;
int flag=0;
while(a2>0)
{
a2/=10; //Moves to the left by one digit
if(a2==0) //If there are odd no. of digits
{
flag=1;
break;
}
a2/=10; //Moves to the left by one digit
a1/=10; //Moves to the left by one digit
}
System.out.print(flag!=1?"No Mid Exists":a1%10);

Your "math" is working correctly. The one thing you can: compute the length (number of digits) within your number upfront, to avoid "iterating" the number twice - so you can determine if that number of digits is even or odd without "iterating" the number:
int n = 1234;
int length = (int)(Math.log10(n)+1);
should give you 4 for 1234, and 5 for 12345.
But beyond that: you can express information in different ways. For example: you can turn an int value into a string.
String asStr = Integer.toString(123456);
And now: you can easily check the length of that string; and you can directly access the corresponding character!
The only thing to keep in mind: characters representing numbers like '1', '2', ... have different numerical values as int 1, 2, ... (see an ASCII table; as '1' is 49 when regarding its numerical value)!

this answer has less code, but wouldn't take much in performance i think:
int a1 = 12334;
int a = a1;
int middle = 0;
int noOfDigits = 0;
while (a1 != 0) {
a1 = a1 / 10;
noOfDigits++;
}
if (noOfDigits % 2 == 1) {
for (int i = 0; i < (noOfDigits / 2) + 1; i++) {
middle = a % 10;
a = a / 10;
}
System.out.println(middle);
} else {
System.out.println("No mid existing");
}

Using only math
int num = 123406789;
int countDigits = (int)Math.ceil(Math.log10(num));
int midIndex = (int)Math.ceil(countDigits/2);
int x = num / (int)Math.pow(10, midIndex);
int middleDigit = x % 10;
System.out.println(middleDigit);

Related

Find consecutive number of 1's

I am trying to find the number of consecutive 1's in a binary.
Example: Convert Decimal number to Binary and find consecutive 1's
static int count = 0;
static int max = 0;
static int index = 1;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
scan.close();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);
for (int i = 0; i < b.length(); i++) {
if (arr[i] == index) {
count++;
} else {
count = 0;
}
if (count > max) {
max = count;
}
}
System.out.println(max);
}
I am always getting 0. It seems as if the condition is not working in my code. Could you please provide your suggestion on where am I going wrong with this?
Your qusetion is not so clear but AFAIU from your algorithm, you're trying to find number of most repeated 1's. The issue is that when you're doing comparision if (arr[i] == index), the comparison is done with a char and integer because type of arr is char array. Isn't it? To overcome it either you can convert the char array into integer or convert the integer index value into char. I do this to overcome it.
if (arr[i] == index + '0')
It is not an really elegant solution. I assume that you're a student and want you to show what's wrong. If I want to do something like this, I use,
private static int maxConsecutiveOnes(int x) {
// Initialize result
int count = 0;
// Count the number of iterations to
// reach x = 0.
while (x!=0) {
// This operation reduces length
// of every sequence of 1s by one.
x = (x & (x << 1));
count++;
}
return count;
}
Its trick is,
11101111 (x)
& 11011110 (x << 1)
----------
11001110 (x & (x << 1))
^ ^
| |
trailing 1 removed
As I understand correctly, you want to count maximum length of the group of 1 in the binary representation of the int value. E.g. for 7917=0b1111011101101 result will be 4 (we have following groups of 1: 1, 2, 3, 4).
You could use bit operations (and avoid to string convertation). You have one counter (to count amount of 1 in the current group) and max with maximum of all such amounts. All you need is just to check lowest bit for 1 and then rotate value to the right until it becomes 0, like getMaxConsecutiveSetBit1.
Or just do it in a very simple way - convert it to the binary string and count amount of 1 characters in it, like getMaxConsecutiveSetBit2. Also have one counter + max. Do not forget, that char in Java is an int on the JVM level. So you do not have compilation problem with compare char with int value 1, but this is wrong. To check if character is 1, you have to use character - '1'.
public static void main(String[] args) {
try (Scanner scan = new Scanner(System.in)) {
int val = scan.nextInt();
System.out.println(Integer.toBinaryString(val));
System.out.println(getMaxConsecutiveSetBit1(val));
System.out.println(getMaxConsecutiveSetBit2(val));
}
}
public static int getMaxConsecutiveSetBit1(int val) {
int max = 0;
int cur = 0;
while (val != 0) {
if ((val & 0x1) != 0)
cur++;
else {
max = Math.max(max, cur);
cur = 0;
}
val >>>= 1;
}
return Math.max(max, cur);
}
public static int getMaxConsecutiveSetBit2(int val) {
int max = 0;
int cur = 0;
for (char ch : Integer.toBinaryString(val).toCharArray()) {
if (ch == '1')
cur++;
else {
max = Math.max(max, cur);
cur = 0;
}
}
return Math.max(max, cur);
}
Change type of index variable from int to char:
static char index = 1;
to let the comparison made in this line:
if (arr[i] == index)
do its job. Comparing int 1 (in your code this is the value stored in index variable) with char '1' (in your example it's currently checked element of arr[]) checks if ASCII code of given char is equal to int value of 1. This comparison is never true as char '1' has an ASCII code 49 and this is the value that is being compared to value of 1 (49 is never equal to 1).
You might want to have a look at ASCII codes table in the web to see that all characters there have assigned corresponding numeric values. You need to be aware that these values are taken into consideration when comparing char to int with == operaror.
When you change mentioned type of index to char, comparison works fine and your code seems to be fixed.
Using your for loop structure and changing a few things around while also adding some other stats to report which could be useful. I count the total number of 1's in the number, the number of consecutive 1's (groups of 1's), and the greatest number of consecutive 1's. Also your for loop was looping based on the string length and not the array's length which is just sort of nit picky. Here is the code
int count = 0;
int max = 0;
char index = '1';
int consecutiveOnePairs = 0;
int numberOfOnes = 0;
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);
for (int i = 0; i < arr.length; i++) {
if (arr[i] == index)
{
count++;
numberOfOnes++;
}
if((i + 1 == arr.length && count > 1) || arr[i] != index)
{
if(count > 1)
consecutiveOnePairs++;
if (count > max)
max = count;
count = 0;
}
}
System.out.println("Total Number of 1's in " + n + " is " + numberOfOnes);
System.out.println("Total Number of Consecutive 1's in " + n + " is " + consecutiveOnePairs);
System.out.println("Greatest Number of Consecutive 1's in " + n + " is " + max);
scan.close();
Output
13247
11001110111111
Total Number of 1's in 13247 is 11
Total Number of Consecutive 1's in 13247 is 3
Greatest Number of Consecutive 1's in 13247 is 6
511
111111111
Total Number of 1's in 511 is 9
Total Number of Consecutive 1's in 511 is 1
Greatest Number of Consecutive 1's in 511 is 9
887
1101110111
Total Number of 1's in 887 is 8
Total Number of Consecutive 1's in 887 is 3
Greatest Number of Consecutive 1's in 887 is 3
If you use Java 8, you can try this snippet:
public int maxOneConsecutive(int x)
{
String intAsBinaryStr = Integer.toBinaryString(x);
String[] split = intAsBinaryStr.split("0");
return Arrays.stream(split)
.filter(str -> !str.isEmpty())
.map(String::length)
.max(Comparator.comparingInt(a -> a)).orElse(0);
}

How to add together an array representation of an integer with different number of digits?

How would I add together two integers with different number of digits, using an array, without causing an out of bounds exception?
For example: 500 + 99
each digit is an element of the array
This is how I'm doing it right now:
int aIILength = infiniteInteger.length-1;
int bIILength = anInfiniteInteger.infiniteInteger.length-1;
for(int f = aIILength; f >0; f--){
int aTempNum = infiniteInteger[f];
int bTempNum = anInfiniteInteger.infiniteInteger[f];
result = aTempNum + bTempNum;
//array representation of sum
tempArray[f] = result;
}
Let the counter in the loop go from 1 and up, and use it to access the digits from the end of each array.
You need a carry to hold the overflow of adding each set of digits.
Loop until you run out of digits in both arrays, and carry is zero.
Check the range when you access the digits from the arrays, and use zero when you run out of digits.
int aIILength = infiniteInteger.length;
int bIILength = anInfiniteInteger.infiniteInteger.length;
int carry = 0;
for(int f = 1; f <= aIILength || f <= bIILength || carry > 0; f++){
int aTempNum;
if (f <= aIILength) {
aTempNum = infiniteInteger[aIILength - f];
} else {
aTempNum = 0;
}
int bTempNum;
if (f <= bIILength) {
bTempNum = anInfiniteInteger.infiniteInteger[bIILength - f];
} else {
bTempNum = 0;
}
result = aTempNum + bTempNum + carry;
tempArray[tempArray.length - f] = result % 10;
carry = result / 10;
}
Note: Make tempArray longer than both the operand arrays, so that it has place for a potential carry to the next digit.

Reversing an integer in Java using a for loop

This is a homework problem
How would I reverse an integer in Java with a for loop? The user will input the integer (I don't know how long it will be) and I need to reverse it. ie: If they enter 12345, my program returns 54321.
Here's the catch, you can't use String, StringBuffer, arrays, or other advanced structures in this problem.
I have a basic idea of what I need to do. My problem is...in the for loop, wouldn't the condition need to be x < the length of the integer (number of digits)? How would I do that without String?
Thanks for any input, and I'll add more information if requested.
EDIT:
Of course, after introspection, I realized I should use another for loop to do this. What I did was create a for loop that will count the digits by dividing by 10:
int input = scan.nextInt();
int n = input;
int a = 0;
for (int x = 0; n > 0; x++){
n = n/10;
a = a + 1;
}
EDIT 2:
This is what I have
int input = scan.nextInt();
int n = input;
int a = 0;
int r = 0;
for (int x = 0; n > 0; x++){
n = n/10;
a = a + 1;
}
for (int y = 0; y < n; y++) {
r = r + input%10;
input = input/10;
}
System.out.println(input);
When I run it, it isn't reversing it, it's only giving me back the numbers. ie: if I put in 1234, it returns 1234. This doesn't make any sense to me, because I'm adding the last digit to of the input to r, so why wouldn't it be 4321?
While your original number is nonzero, take your result, multiply it by 10, and add the remainder from dividing the original by 10.
For example, say your original number is 12345. Start with a result of 0.
Multiply result by 10 and add 5, giving you 5. (original is now 1234.)
Multiply result by 10 and add 4, giving you 54. (original is now 123.)
Multiply result by 10 and add 3, giving you 543. (original = 12.)
Multiply result blah blah 5432. (original = 1.)
Multiply, add, bam. 54321. And 1 / 10, in int math, is zero. We're done.
Your mission, should you choose to accept it, is to implement this in Java. :) (Hint: division and remainder are separate operations in Java. % is the remainder operator, and / is the division operator. Take the remainder separately, then divide the original by 10.)
You will need to use math to access each of the digits. Here's a few hints to get your started:
Use the % mod operator to extract the last digit of the number.
Use the / division operator to remove the last digit of the number.
Stop your loop when you have no more digits in the number.
This might not be the proper way but
public static int reverseMe(int i){
int output;
String ri = i + "";
char[] inputArray = ri.toCharArray();
char[] outputArray = new char[inputArray.length];
for(int m=0;m<inputArray.length;m++){
outputArray[inputArray.length-m-1]=inputArray[m];
}
String result = new String(outputArray);
output = Integer.parseInt(result);
return output;
}
public static void reverse2(int n){
int a;
for(int i = 0; i < n ; i ++){
a = n % 10;
System.out.print(a);
n = n / 10;
if( n < 10){
System.out.print(n);
n = 0;
}
}
}
here is the Answer With Correction of Your Code.
import static java.lang.Math.pow;
import java.util.*;
public class MyClass {
public static void main(String args[]) {
Scanner scan=new Scanner(System.in);
int input = scan.nextInt();
int n = input;
int a = 0;
int r = 0;
for (; n > 0;){
n = n/10;
a = a + 1;
}
for (int y = 0; y < input;a--) {
r =(int)( r + input%10*pow(10,a-1));
input = input/10;
}
System.out.println(r);
}
}

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

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

Iterate through each digit in a number

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

Categories