How to determine if a number is monotonically decreasing? - java

I'm working on the following problem:
The number n is given as input
Find out if it's monotonic?
A monotonic number is called - that number of numbers in which
monotonically decrease or increase monotonically. For example: 110,
111, 122, 123, 455, 554. - are monotonic. 101, 121, 231 are
non-monotonic.
Constraint: Arrays and strings cannot be used.
I wrote a function to check for a monotonically increasing number:
public static boolean isMonotonic(int num) {
int n = num; // Copy of num to be modified
int b = (n/10)%10; // Step for a number if it is monotone
n /= 10;
if (num < 100) return true; // all two-digit numbers are monotonic
while (n > 0 && n > b) {
if ((n/10)%10 != b){
return false;
}
n /= 10;
}
return true;
}
But I don't know how to make a function for a monotonically decreasing number.

Because according to your requirement the digits of a valid monotonic number can be equal (e.g. 110, 455) the decreasing order and increasing order can be easily confused while examining the digits. And we also have a case when all digits are equal, i.e. the number is neither increasing, no decreasing, but it's considered to be a valid monotonic number (e.g. 111).
I've come up with the following algorithm:
Maintain three boolean flags representing three cases when a number can be considered monotonic, described above. To initialize these flags, we need to access both the first and the last digits of the given number. Because adjacent digits can be equal, only comparison of the first and the last digits would provide sufficient information regarding expected ordering of the number. Here is how all three flags would be initialized:
isEqual = first == last;
isIncreasing = first >= last;
isDeceasing = first <= last;
Maintain a variable holding the value of the previous digit.
Iterate over the digits of the given number and compare the next and previous digits. If conditions are consistent with the flags - proceed iterating further, otherwise invalidate the number returning false.
As a small optimization we can cut out all numbers that are less the then 100 because according to the requirements are monotonic.
That's how implementation might look like:
public static boolean isMonotonic(int num) {
// NOTE: use Math.abs() to adjust the input if negative values are allowed
if (num <= 100) return true; // early kill for small number
int last = num % 10;
int first = num / (int) Math.pow(10, (int) Math.log10(num));
int prev = last;
num /= 10;
boolean isEqual = isEqual(first, last);
boolean isIncreasing = isIncreasing(first, last);
boolean isDeceasing = isDecreasing(first, last);
while (num > 0) {
int next = num % 10;
if (isEqual && !isEqual(next, prev)) return false; // next is passed before previous because we are iterating from right to left
if (isIncreasing != isIncreasing(next, prev) && isDeceasing != isDecreasing(next, prev)) {
return false;
}
prev = next;
num /= 10;
}
return true; // the number is proved to be monotonic
}
public static boolean isEqual(int left, int right) {
return left == right;
}
public static boolean isIncreasing(int left, int right) {
return left <= right;
}
public static boolean isDecreasing(int left, int right) {
return left >= right;
}
main()
public static void main(String[] args) {
System.out.println("Digits are equal:");
System.out.println(111 + " " + isMonotonic(111));
System.out.println(333 + " " + isMonotonic(333));
System.out.println(999 + " " + isMonotonic(999));
System.out.println("Increasing:");
System.out.println(189 + " " + isMonotonic(189));
System.out.println(577 + " " + isMonotonic(577));
System.out.println(779 + " " + isMonotonic(779));
System.out.println("Decreasing");
System.out.println(775 + " " + isMonotonic(775));
System.out.println(831 + " " + isMonotonic(831));
System.out.println(99333 + " " + isMonotonic(99333));
System.out.println("Non-monotonic");
System.out.println(101 + " " + isMonotonic(101));
System.out.println(45551 + " " + isMonotonic(45551));
System.out.println(95559 + " " + isMonotonic(95559));
}
Output:
Digits are equal:
111 true
333 true
999 true
Increasing:
189 true
577 true
779 true
Decreasing
775 true
831 true
99333 true
Non-monotonic
101 false
45551 false
95559 false

An easy way to solve this without dealing with n/10's is converting num into a string
public static boolean isMonotonicDecreasing(int num) {
//First, convert num into a string
String numString = String.valueOf(num);
//Iterate across numString - 1
for (int i = 0; i < numString.length() - 1; i++){
//If the current digit (character at index i, converted to integer)
//is less than the next digit, return false
if ((int)numString.charAt(i) < (int)numString.charAt(i+1)){
return false;
}
}
//Return true after reaching end of loop
return true;
}

To compare if the digits are going up or down, compare the the previous digit and the current digit. Each iteration, we must update previous digit to current digit and move current digit to the next digit and shift the digits in the integer to the right.
You need two boolean variables: tracking monotonic increasing and monotonic decreasing. Finally, return the OR of the two boolean variables.
static boolean isMonotonic(int n){
boolean inc = true; //assume monotonic increasing
boolean dec = true; //assume monotonic decreasing
int prev = n%10; //previous is right most digit
n/=10; //shift digits to the right
while(n > 0){
int cur = n%10; //current is right most digit
inc &= prev >= cur; //is monotonic increasing ?
dec &= prev <= cur; //is monotonic decreasing ?
prev = cur; //previous is set to current digit
n/=10; //shift digits to the right.
}
return inc || dec;
}

Let's introduce int order which is +1 if we have increasing sequence, -1 in case of decreasing sequence and 0 if
we don't know it so far (for instance ...111111). Then all we should do is to llop over digits:
public static bool isMonotonic(int num) {
if (num > -100 && num < 100)
return true;
int order = 0;
int prior = num % 10;
for (; num != 0; num /= 10) {
int current = num % 10;
if (order > 0 && current < prior || order < 0 && current > prior)
return false;
if (current != prior)
order = Math.sign(current - prior);
prior = current;
}
return true;
}
Another possibility is to try to find counter example: a digit which is bigger than its neighbors or smaller than its neighbors.

Related

I want to check if a number is binary or not in decimal numbers but it didnt work

I want to check if a number if binary or not in decimal numbers but it didnt work
from numbera 1 to n.
for example from 1 to 10 we have 2 decimal numbers that contains 0,1.How can i change it?
import java.util.Scanner;
public class Main
{
public static void main(String args[]) {
int r = 0, c = 0, num, b;
int count=0;
Scanner sl = new Scanner(System.in);
System.out.println("Enter a number");
num = sl.nextInt();
for (int i = 1; i <= num; i++) {
if ((i % 10 == 0) || (i % 10 == 1))
c++;
r++;
i = i / 10;
}
if (c == r)
count++;
else{
}
System.out.println(count);
}
}
I am not a java dev so maybe my answer is not good.But you can use your number as str then check if the str is constituted only by 0 and 1
maybe this could help: : How to check if only chosen characters are in a string?
have a nice day
Here's how you can do it in an elegant way ...
// Function to check if number
// is binary or not
public static boolean isBinaryNumber(int num)
{
if(num == 1 || num == 0) return true
if (num < 0) return false;
// Get the rightmost digit of
// the number with the help
// of remainder '%' operator
// by dividing it with 10
while (num != 0) {
// If the digit is greater
// than 1 return false
if (num % 10 > 1) {
return false;
}
num = num / 10;
}
return true;
}
Here, will use 2 loops, one for range and one for checking if it's binary or not.
Instead of c and r, we will use flag and break in order to skip unnecessary iteration.
int count=0;
boolean flag = true;
for(int i=1;i<=num;i++)
{
for(int j=i;j>0;j=j/10)
{
// if remainder is not 0 and 1, then it means it's not binary
// so we set flag as false
// and using break to break out of the current(inner) loop, it's no longer needed to check remaining digits.
if (j%10 > 1)
{
flag = false;
break;
}
}
// if flag is true, that means it's binary and we increment count.
// if flag is flase, that means it's not binary
if(flag)
count++;
// here we reset flag back to true
flag = true
}
System.out.println(count);
You can also do as #jchenaud suggested. converting it to string and check if it only contains 0 and 1.

Represent an Integer as a sum of Consecutive positive integers

I am writing code for counting the number of ways an integer can be represented as a sum of the consecutive integers. For Example
15=(7+8),(1+2+3+4+5),(4+5+6). So the number of ways equals 3 for 15.
Now the input size can be <=10^12. My program is working fine till 10^7(i think so, but not sure as i didnt check it on any online judge. Feel free to check the code for that)
but as soon as the i give it 10^8 or higher integer as input. it throws many runtime exceptions(it doesnt show what runtime error). Thanks in advance.
import java.io.*;
//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
public static long count = 0;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
driver(num);
System.out.println("count = " + count);
}
public static void driver(long num)
{
long limit = num / 2;
for(long i = 1 ; i <= limit ; i++)
{
func(i,num);
}
}
public static void func(long i,long num)
{
if(i < num)
{
func(i + 1,num - i);
}
else if(i > num)
{
return;
}
else
{
count++;
}
}
}
Use some math: if arithmetic progression with difference 1 starts with a0 and contains n items, then its sum is
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
note that the second summand rises as quadratic function. So instead of checking all a0 in range S/2, we can check all n is smaller range
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(I used some higher approximation).
Just test whether next expression gives integer positive result
a0 = (S - n * (n - 1) / 2) / n
Recursive function isn't suitable when you have big input size like your case.
The maximum depth of the java call stack is about 8900 calls and sometimes only after 7700 calls stack overflow occurs so it really depends on your program input size.
Try this algorithm I think it worked for your problem:
it will work fine until 10^9 after that it will take much more time to finish running the program.
long sum = 0;
int count = 0;
long size;
Scanner in = new Scanner(System.in);
System.out.print("Enter a number <=10^12: ");
long n = in.nextLong();
if(n % 2 != 0){
size = n / 2 + 1;
}
else{
size = n / 2;
}
for(int i = 1; i <= size; i++){
for(int j = i; j <= size; j++){
sum = sum + j;
if(sum == n){
sum = 0;
count++;
break;
}
else if(sum > n){
sum = 0;
break;
}
}
}
System.out.println(count);
Output:
Enter a number <=10^12: 15
3
Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)
There's a really excellent proof that the answer can be determined by solving for the unique odd factors (Reference). Essentially, for every odd factor of a target value, there exists either an odd series of numbers of that factor multiplied by its average to produce the target value, or an odd average equal to that factor that can be multiplied by double an even-sized series to reach the target value.
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}
As #MBo noted, if a number S can be partitioned into n consecutive parts, then S - T(n) must be divisible by n, where T(n) is the n'th triangular number, and so you can count the number of partitions in O(sqrt(S)) time.
// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
assert sum > 0: sum;
int n = 2;
int numberOfPartitions = 0;
long triangularNumber = n * (n + 1) / 2;
while (sum - triangularNumber >= 0) {
long difference = sum - triangularNumber;
if (difference == 0 || difference % n == 0)
numberOfPartitions++;
n++;
triangularNumber += n;
}
return numberOfPartitions;
}
A bit more math yields an even simpler way. Wikipedia says:
The politeness of a positive number is defined as the number of ways it can be expressed as the sum of consecutive integers. For every x, the politeness of x equals the number of odd divisors of x that are greater than one.
Also see: OEIS A069283
So a simple solution with lots of room for optimization is:
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}

Java method on odd digits extraction

Write a method extractOddDigits() which extracts the odd digits from a positive number n, and
combines the odd digits sequentially into a new number. The new number is returned back to the
calling method. If the input number n does not contain any odd digits, then returns -1.
For examples, if
n=1234567, then 1357 is returned; and if n=28, then –1 is returned.
Test cases:
(1) n : 12345;
(2) n : 54123;
(3) n : 246;
(4) n : -12 (give an error message)
Expected outputs:
(1) oddDigits = 135;
(2) oddDigits = 513;
(3) oddDigits = -1;
(4) oddDigits = Error input!!
This is the method i have done, but the output is
(1) oddDigits = 135;
(2) oddDigits = 513;
(3) oddDigits = -1;
(4) oddDigits = -1
The last output should be Error input!
public static long extractOddDigits(long n){
String output = "";
if(n < 0) // check if negative
{
output = "Error Input!!";
}
if(n % 2 == 0){ //check even
output = "-1";
}
while(n > 0) {
int left = (int) (n % 10);
if(left % 2 != 0)
output = left + output;
n /= 10;
}
System.out.println("oddDigit = " + output);
}
How to i check if n is a negative number then goes to Error input?
Your problem is that the first two if may assign a value to output, but not in a exclusive way, you can find a numer which is negative AND is also even AND it contains odd numbers. So you must ensure your code isolates each option.
Besides, your requirements say that the method must return the number, not just print it, so you method should be returning long and not void, but I'll leave that as part of your homework ;)
public static void extractOddDigits(long n){
String output = "";
if(n < 0) {
output = "Error Input!!";
} else {
while(n > 0) {
int left = (int) (n % 10);
if (left % 2 != 0) {
output = left + output;
}
n /= 10;
}
}
if (output.equals("") {
output="-1";
}
System.out.println("oddDigit = " + output);
}
First of all just because number is even, it does not imply that it does not contain any odd digits.
So:
if(n % 2 == 0){ //check even
output = "-1";
}
is wrong. Also you dont need to type cast the (n % 10); to int.
You can keep a boolean variable foundOdd, that keeps track of whether so far we have found any odd digits, and in the end if that remains false, we can simply print -1.
So the right code is:
int n = 246;
String output="";
boolean foundOdd=false;
if(n < 0) // check if negative
output = "Error Input!!";
else
{
while(n > 0)
{
int left = (n % 10);
if(left % 2 != 0)
{output = left + output; foundOdd = true;}
n /= 10;
}
}
if(foundOdd)
System.out.println("oddDigit = " + output);
else System.out.println(-1);
The problem is:
when n=-12, you are assigning output "Error Input!!"
and then since also n%2==0, you are overwriting output to "-1"
Also, your logic - if n is divisible by 2 , it will not have odd digits, is incorrect
This code checks for all digits if it contains any even one.
public static void extractOddDigits(long n){
String output = "";
if(n < 0) // check if negative
{
output = "Error Input!!";
}
else {
//Iterate through the digits
while(n>0){
long lastDigit = n%10;
if(lastDigit % 2 != 0) { //for odd digit
output = lastDigit+output;
}
n = n/10;
}
}
//If no odd digits
if(output.equals("")) {
output = "-1";
}
System.out.println(output);
}
If you do not want the method to run further if n < 0, then ,
if(n < 0) // check if negative
{
output = "Error Input!!";
System.out.println(output);
return;
}

nth Binary palindrome with efficient time complexity

Given an integer N, i am trying to find the nth binary palindrome.I have written the following code but it is not efficient.is there a more efficient way in terms of time complexity.
I was trying it out as a problem online and i was supposed to output in 1 sec or less but for every input it takes 2 seconds.
public static Boolean Palind(String n){
String reverse = "";
int length = n.length();
for(int i = length - 1; i >=0;i--){
reverse = reverse + n.charAt(i);
}
if(n.equals(reverse)){
return true;
}
else{
return false;
}
}
public static int Magical(int n){
ArrayList<Integer> res = new ArrayList<Integer>();
for(int i = 1; i < Math.pow(2, n);i++){
if(Palind(Integer.toBinaryString(i))){
res.add(i);
}
}
return res.get(n-1);
}
The relevant OEIS entry (A006995) has a lot of nice tips if you read through it. For example, a(2^n-1)=2^(2n-2)-1 lets you skip right to the (2n - 1)th palindrome really quickly.
It also gives several implementations. For example, the Smalltalk implementation works like this (note that the input value, n, starts with 1 for the first palindrome, 0):
public static final int nthBooleanPalindrome(int n) {
if (n == 1) return 0;
if (n == 2) return 1;
int m = 31 - Integer.numberOfLeadingZeros(n);
int c = 1 << (m - 1);
int b;
if (n >= 3*c) {
int a = n - 3*c;
int d = 2*c*c;
b = d + 1;
int k2 = 1;
for (int i = 1; i < m; i++) {
k2 <<= 1;
b += a*k2/c%2*(k2 + d/k2);
}
}
else {
int a = n - 2*c;
int d = c*c;
b = d + 1 + (n%2*c);
int k2 = 1;
for (int i = 1; i < m - 1; i++) {
k2 <<= 1;
b += a*k2/c%2*(k2 + d/k2);
}
}
return b;
}
Try something like this maybe?
public static void main(String[] args) {
for (int i = 1; i < 65535; i++) {
System.out.println(
i + ": " + getBinaryPalindrom(i) + " = " + Integer.toBinaryString(getBinaryPalindrom(i)));
}
}
public static int getBinaryPalindrom(int N) {
if (N < 4) {
switch (N) {
case 1:
return 0;
case 2:
return 1;
case 3:
return 3;
}
throw new IndexOutOfBoundsException("You need to supply N >= 1");
}
// second highest to keep the right length (highest is always 1)
final int bitAfterHighest = (N >>> (Integer.SIZE - Integer.numberOfLeadingZeros(N) - 2)) & 1;
// now remove the second highest bit to get the left half of our palindrom
final int leftHalf = (((N >>> (Integer.SIZE - Integer.numberOfLeadingZeros(N) - 1)) & 1) << (Integer.SIZE -
Integer.numberOfLeadingZeros(N) - 2)) | ((N << (Integer.numberOfLeadingZeros(N) + 2)) >>> (Integer.numberOfLeadingZeros(N) + 2));
// right half is just the left reversed
final int rightHalf = Integer.reverse(leftHalf);
if (Integer.numberOfLeadingZeros(leftHalf) < Integer.SIZE / 2) {
throw new IndexOutOfBoundsException("To big to fit N=" + N + " into an int");
}
if (bitAfterHighest == 0) {
// First uneven-length palindromes
return (leftHalf << (Integer.SIZE - Integer.numberOfLeadingZeros(leftHalf)) - 1) | (rightHalf
>>> Integer.numberOfTrailingZeros(rightHalf));
} else {
// Then even-length palindromes
return (leftHalf << (Integer.SIZE - Integer.numberOfLeadingZeros(leftHalf))) | (rightHalf
>>> Integer.numberOfTrailingZeros(rightHalf));
}
}
The idea is that each number will become a palindrome once it reverse is added. To have the halves correctly aligned the halves just need to be shifted in place.
The problem why this has gotten a bit complex is that all uneven-length palindromes of a given leftHalf length come before all even-length palindromes of a given leftHalf length. Feel free to provide a better solution.
As int has 32 bit in Java there is a limit on N.
int-Version on ideone.com
And a BigInteger-version to support big values. It is not as fast as the int-version as the byte[]-arrays which store the value of the BigInteger create some overhead.
public static void main(String[] args) {
for (BigInteger i = BigInteger.valueOf(12345678); i.compareTo(BigInteger.valueOf(12345778)) < 0; i = i
.add(BigInteger
.ONE)) {
final BigInteger curr = getBinaryPalindrom(i);
System.out.println(i + ": " + curr + " = " + curr.toString(2));
}
}
public static BigInteger getBinaryPalindrom(BigInteger n) {
if (n.compareTo(BigInteger.ZERO) <= 0) {
throw new IndexOutOfBoundsException("You need to supply N >= 1");
} else if (n.equals(BigInteger.valueOf(1))) {
return BigInteger.valueOf(0);
} else if (n.equals(BigInteger.valueOf(2))) {
return BigInteger.valueOf(1);
} else if (n.equals(BigInteger.valueOf(3))) {
return BigInteger.valueOf(3);
}
final int bitLength = n.bitLength() - 1;
// second highest to keep the right length (highest is always 1)
final boolean bitAfterHighest = n.testBit(bitLength - 1);
// now remove the second highest bit to get the left half of our palindrom
final BigInteger leftHalf = n.clearBit(bitLength).setBit(bitLength - 1);
// right half is just the left reversed
final BigInteger rightHalf;
{
byte[] inArray = leftHalf.toByteArray();
byte[] outArray = new byte[inArray.length];
final int shiftOffset = Integer.SIZE - Byte.SIZE;
for (int i = 0; i < inArray.length; i++) {
outArray[inArray.length - 1 - i] = (byte) (Integer.reverse(inArray[i]) >>> shiftOffset);
}
rightHalf = new BigInteger(1, outArray).shiftRight(outArray.length * Byte.SIZE - bitLength);
}
if (!bitAfterHighest) {
// First uneven-length palindromes
return leftHalf.shiftLeft(bitLength - 1).or(rightHalf);
} else {
// Then even-length palindromes
return leftHalf.shiftLeft(bitLength).or(rightHalf);
}
}
I have the same idea with #Kiran Kumar: you should not count number one by one to find if it is a binary palindrome which is too slow, but rather find the internal pattern that number has.
List the number in binary string one by one, you can find the pattern:
0
1
11
101
1001
1111
...
1......1
And the following is some math problem:
We have 2^round_up((L-2)/2) palindrome of number with length L in binary format.
Sum up every shorter length number, we get following len to sum mapping:
for (int i = 1; i < mapping.length; i++) {
mapping[i] = (long) (mapping[i - 1] + Math.pow(2, Math.ceil((i - 1) * 1.0 / 2)));
}
If we find N range in [count(L), count(L+1)), we can concat it with remaining number:
public static long magical(long n) {
if (n == 0 || n == 1) {
return n;
}
long N = n - 2;
return Long.parseLong(concat(N), 2);
}
private static String concat(long N) {
int midLen = Arrays.binarySearch(indexRange, N);
if (midLen < 0) {
midLen = -midLen - 1;
}
long remaining = N - indexRange[midLen];
String mid = mirror(remaining, midLen);
return '1' + mid + '1';
}
private static String mirror(long n, int midLen) {
int halfLen = (int) Math.ceil(midLen * 1.0 / 2);
// produce fixed length binary string
final String half = Long.toBinaryString(n | (1 << halfLen)).substring(1);
if (midLen % 2 == 0) {
return half + new StringBuilder(half).reverse().toString();
} else {
return half + new StringBuilder(half).reverse().toString().substring(1);
}
}
Full code with test for produce large possible long can be found in my git repo.
Idea to optimize,
Let's look at the palindrome sequence 0, 1, 11, 101, 111, 1001 etc...
All numbers must begin and end with 1, So the middle bits only changes and midle substring should be palindrome for full string to become palindrome,
So let's take a 2 digit binary number - one palindrome is possible.
The binary of the decimal 3 is a palindrome. 11
For a 3 digit binary number 2 palindromes are possible, 2*(no of 1 digit palindrome)
The binary of the decimal 5 is a palindrome. 101
The binary of the decimal 7 is a palindrome. 111
For 5 digit binary number 4 palindromes are possible 2*(no of 3 digit palindrome)
10001,10101, 11011, 11111
and so on,
So it will be 2 + 20 + 21 + 22 +...... +2i-N ,
we solve for i and find out the palindrome number.
So by analysing this sequence we get an equation like 2(i/2)+1 -1 = N
where N is the No of palindrome,
and i is the number of bits in the nth palindrome string,
using this we can find the length of the String, from this we can find the string early.
This might be complex, but helps in solving higher values of N quickly....

Java- Builiding a recursion that replace even digits with zero

Hello i need to build a recursion that replace the even digits with zero:
for exmaple - the number 1254 will be 1050
the number 332- will be 330
and the number 24 - will be 0
i started working on it but got pretty clueless after a while
public static int replaceEvenDigitsWithZero(int number){
if(number<1)
return number;
if(number%2==0 && number%10!=0){
int temp=number%10;
return(number/10+replaceEvenDigitsWithZero(number-temp));
}
return(replaceEvenDigitsWithZero(number/10));
}
public static void main(String[] args) {
int num1 = 1254;
System.out.println(num1 + " --> " + replaceEvenDigitsWithZero(num1));
int num2 = 332;
System.out.println(num2 + " --> " + replaceEvenDigitsWithZero(num2));
int num3 = 24;
System.out.println(num3 + " --> " + replaceEvenDigitsWithZero(num3));
int num4 = 13;
System.out.println(num4 + " --> " + replaceEvenDigitsWithZero(num4));
}
}
Since your method only looks at the last digit, it should always call itself with input / 10 when input >= 10.
You then take the value returned by the recursion, multiply it by 10 and add the last digit back, if odd.
public static int replaceEvenDigitsWithZero(int number) {
int result = 0;
if (number >= 10)
result = replaceEvenDigitsWithZero(number / 10) * 10;
if (number % 2 != 0)
result += number % 10;
return result;
}
In case you need a 1-liner, here it goes: ;)
public static int replaceEvenDigitsWithZero(int number) {
return (number%2 == 0 ? 0 : number % 10) + (number<10 ? 0 : 10 * replaceEvenDigitsWithZero(number / 10));
}
Well ... designing a recursive algorithm has always the same steps:
Identify the base case, that is the scenario that will terminate the recursive calls.
Reduce the problem to being smaller (towards the base case).
For this requirement the problem can easily be made smaller by dividing by 10. That also easily leads to the base case: A single digit is the base case. So a quick implementation can be:
public static int replaceEvenDigitsWithZero(int number) {
// I added handling of negative numbers ...
if (number < 0) {
return -replaceEvenDigitsWithZero(-number);
}
// base case
if (number < 10) {
return replaceOneDigit(number);
}
// recursion
int lastDigit = number % 10;
int remainder = number / 10;
return replaceEvenDigitsWithZero(remainder) * 10 + replaceOneDigit(lastDigit);
}
public static int replaceOneDigit(int digit) {
return (digit % 2 == 0) ? 0 : digit;
}
I added a helper method for converting even digits to zero.
The output now is:
1254 --> 1050
332 --> 330
24 --> 0
13 --> 13
You need to take track of the current position in your number.
In your current function, you will return only the first digit of your number (because you divide it by 10 everytime the recursion is called).
public static int replaceEvenDigitsWithZero(int number, int position){
// cancel condition:
if(number < 10 * position) {
return number;
}
// edit number:
if (position > 0) {
int currentNumber = number / (10 * position);
} else {
currentNumber = number;
}
if(currentNumber%2==0){ //even?
int multiplyValue = currentNumber % 10; // get rest of division by 10 (== digit in current position)
number = number - (multiplyValue * (10 * position)); // set current position to zero
}
// recursive call:
return replaceEvenDigitsWithZero(number,position+1);
}
Didn't test my code, but I hope you get an idea of how to do it.
Use replaceEvenDigitsWithZero(num1,0) to start.
1 convert to String
2 F(string): take the first number: replace 2,4,6,8 characters by 0
3 concatenate to F(the remaining string)
4 convert to int

Categories

Resources