Finding if a number is a power of another number recursivly - java

Consider this code
public static boolean isPower(int x, int n) {
if (x == 1)
return (n == 1);
int pow = 1;
while (pow < n)
pow = pow * x;
return (pow == n);
}
The goal is to find if the number x is a power of the number n.I've come up with this algorithm,and it works.I'd like to solve it recursivly as well.I read through the linked post someone put in the coments(https://softwareengineering.stackexchange.com/questions/279004/general-way-to-convert-a-loop-while-for-to-recursion-or-from-a-recursion-to-a)
I tried to replicate,or use the pattern that was provided in the answers.
First I tried to identify what my header,condition loop and tail was.
public static boolean isPower(int x, int n) {
if (x == 1)//header
return (n == 1);//header
int pow = 1;//header
while (pow < n)//condition
pow = pow * x;//loop
return (pow == n);//tail
}
Now I tried to apply the pattern;
public static boolean isPower_recursive(int x,int n) {
if(x == 1)
return (n==1);
return isPower_recursion( x, n, 1);
}
public static boolean isPower_recursion(int x,int n, int pow) {
if( 1 > n) {
return (pow == n);
}
pow = pow * x;
return isPower_recursion(x,n,pow);
}
This only works for the case when both x and n are one,in every other case I get a Stackoverflow error.The compiler says the error happens at the return statement in the isPower_recursive method,which leads me to think that i am not calculating this right.Some insight would be great.

I've solved the problem.I applied the patter wrong,it should look like this.
public static boolean isPower_recursive(int x,int n) {
if(x == 1)
return (n==1);
return isPower_recursion( x, n, 1);
}
public static boolean isPower_recursion(int x,int n, int pow) {
if( pow >= n) {
return (pow == n);
}
pow = pow * x;
return isPower_recursion(x,n,pow);
}

Related

Are return statements always necessary for boolean recursion method calls?

I am trying to add the individual digits of a number together and determine whether the final answer is even or odd.
public static boolean isSumOfDigitsOdd(int n) {
if (n <= 0) {
return false;
} else if (n == 1) {
return true;
} else if (n == 2) {
return false;
} else if (n > 2) {
int temp1 = n % 10;
int temp2 = (n / 10) % 10;
int tempFinal = temp1 + temp2;
while (tempFinal > 2) {
tempFinal -= 2;
}
isDigitSumOdd((n / 100) + tempFinal);
}
}
The issue that I am facing is whether a return statement is always necessary for the recursion call to work. As seen from the code above, when I try runnning it gives out an error message saying that the return type must be a boolean type.
However, after adding in a boolean variable, I was able to get the code to work as shown below.
public static boolean isDigitSumOdd(int n) {
boolean x = false;
if (n <= 0) {
x = false;
} else if (n == 1) {
x = true;
} else if (n == 2) {
x = false;
} else if (n > 2) {
int temp1 = n % 10;
int temp2 = (n / 10) % 10;
int tempFinal = temp1 + temp2;
while (tempFinal > 2) {
tempFinal -= 2;
}
return isDigitSumOdd((n / 100) + tempFinal);
}
return x;
}
In this case, after adding the boolean variable, I could run the code smoothly and it would provide me with the desired outcome.
I am fairly new to recursion and am unsure about why this happens. After looking up online, I could only figure out that a return statement is not necessary only if the return type is a void type.
In any language the return statement is necessary when the return type is non-void. There are 2 errors in the first code:
no reason to put the last else if, as an else would be more appropriate
you must call return isDigitSumOdd((n / 100) + tempFinal); because otherwise your function isn't returning anything.
Instead if you actually call it the function returns the value returned by isDigitSumOdd((n / 100) + tempFinal);. That's the key point of recursion.
Now, I don't know if your code works aside from the errors I mentioned, so here's a cleaner solution. The ^ is a XOR operator.
public static boolean isDigitSumOdd(int n) {
if (n == 0) return false;
return isDigitSumOdd(n/10) ^ n%2 == 1;
}

Greatest Common Divisor Challenge(Euclidean Algorithm)

everyone I've tried to solve the Greatest Common Divisor and it seem running well but i think its long code and I'm new to java and i need some advice what can i improve with the code.
public static void main(String[] args) {
System.out.println(GCD(888,54));
}
public static int GCD(int a, int b){
int r = a % b;
if(r != 0){
int rem = b % r;
if (rem > 10){
int aRem = r % rem;
if (aRem < 10){
return aRem;
}else {
int bRem = rem % aRem;
return bRem;
}
}else {
return rem;
}
}else {
return r;
}
}
}
You can do this using recursion as well.
Try using this code in your method.
public static int GCD(int a, int b){
if(b == 0){
return a;
}
return GCD(b, a%b);
}
The iterative way of implementing GCD in Java is the following:
public static int GCD(int a, int b) {
while (b != 0) {
int temp = a;
a = b;
b = temp%b;
}
return a;
}
This is an alternative to the recursive solution from Peter. The advantage is, that is won't use Stack space that much. It has the same time complexity but better memory complexity (O(1)) and will work for all valid data not risking the StackOverflowError.
You can just do using a for loop.
Sample code.
public static int GCD(int a, int b){
int gcd = 1;
for(int i = 1; i <= a && i <= b; i++){
if(a%i==0 && b%i==0)
gcd = i;
}
return gcd;
}

improve recursion for calculating remainder

I had to write a code to calculate the remainder using a certain way. I know that there are better ways to do it but that's how I have to proceed.
The if (rem(x - 1, y) + 1 == y) is making extra calls. As it enters there every time before getting to the last return, but it is an important step for my algorithm. I was wondering if there was any way to avoid it.
Also, I know that I have to check if y == 0; I am just trying to improve the performance for now.
Thanks
int rem(int x, int y)
{
if (x == 0)
{
return 0;
}
if (rem(x - 1, y) + 1 == y)
{
return 0;
}
return rem((x - 1), y) + 1;
}
I get 9 recursive calls for rem(3/2)
Sure, this is how you can make it much better.
int rem(int x, int y) {
if (x == 0) {
return 0;
}
int ret = rem(x - 1, y);
if (ret + 1 == y) {
return 0;
}
return ret + 1;
}
We can just call the function once and store its output in a variable.
Yeah sure, In java you do this in following way:
public static void main(String args[]) {
int remainder = remainder(3,2);
System.out.println(remainder);
}
static int remainder(int n1, int n2) {
int x;
x = n1;
if (x >= n2) {
x = x - n2;
remainder(x, n2);
}
return x;
}
Note: I've not added condition to check 0 in the code.
Hope this helps.

Closed expression, in terms of n

I have been trying to derive an expression in terms of n for the following. The closest I have been by the result is with log_2(n), (base 2). Thank you :)
public static int v(int n) {
int r = 0;
for(int i=1;i<n;i*=2) {
r=r+1;
}
return r;
}
Is this good enough for you:
public static int v2(int n) {
if(n <= 1)
return 0;
return (int) (Math.log(n - 1) / Math.log(2)) + 1;
}
In other words log_2(n-1)+1 for n > 1 and 0 otherwise.

Faster GCD(n, m) in Java?

I'm working on something that's going to need to use the GCD algorithm quite a bit, and I'd like it to be as fast as possible. I've tried the normal method, binary method, and a memoisation method I thought would work better than it did. I copied the binary method from here, with minor tweaks.
I've been using a class called TestGCD for testing, here's the whole thing:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestGCD
{
private static class Pair<A>
{
private final A a_one;
private final A a_two;
public Pair(A a_one, A a_two)
{
this.a_one = a_one;
this.a_two = a_two;
}
#Override
public boolean equals(Object object)
{
if (this == object)
return true;
if (object == null)
return false;
if (!(object instanceof Pair))
return false;
final Pair other = (Pair) object;
if (a_one == null)
if (other.a_one != null)
return false;
if (a_two == null)
if (other.a_two != null)
return false;
if (a_one.equals(other.a_one))
if (a_two.equals(other.a_two))
return true;
if (a_one.equals(other.a_two))
if (a_two.equals(other.a_one))
return true;
return false;
}
public A getFirst()
{
return a_one;
}
public A getSecond()
{
return a_two;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
final int aOneHash = a_one == null ? 0 : a_one.hashCode();
final int aTwoHash = a_two == null ? 0 : a_two.hashCode();
int resultOneWay = prime * result + aOneHash;
resultOneWay += prime * result + aTwoHash;
int resultOtherWay = prime * result + aTwoHash;
resultOtherWay += prime * result + aOneHash;
result += resultOneWay + resultOtherWay;
return result;
}
#Override
public String toString()
{
return String.format("%s, %s", a_one, a_two);
}
}
private final static Map<Pair<Integer>, Integer> STORAGE = new HashMap<>();
private static void addNewPairs(List<Pair<Integer>> newPairs, int result)
{
for (final Pair<Integer> pair : newPairs)
STORAGE.put(pair, result);
}
private static int gcd(int x, int y)
{
if (x == 0)
return y;
if (y == 0)
return x;
int gcdX = Math.abs(x);
int gcdY = Math.abs(y);
if (gcdX == 1 || gcdY == 1)
return 1;
while (gcdX != gcdY)
if (gcdX > gcdY)
gcdX -= gcdY;
else
gcdY -= gcdX;
return gcdX;
}
private static int gcdBinary(int x, int y)
{
int shift;
/* GCD(0, y) == y; GCD(x, 0) == x, GCD(0, 0) == 0 */
if (x == 0)
return y;
if (y == 0)
return x;
int gcdX = Math.abs(x);
int gcdY = Math.abs(y);
if (gcdX == 1 || gcdY == 1)
return 1;
/* Let shift := lg K, where K is the greatest power of 2 dividing both x and y. */
for (shift = 0; ((gcdX | gcdY) & 1) == 0; ++shift)
{
gcdX >>= 1;
gcdY >>= 1;
}
while ((gcdX & 1) == 0)
gcdX >>= 1;
/* From here on, gcdX is always odd. */
do
{
/* Remove all factors of 2 in gcdY -- they are not common */
/* Note: gcdY is not zero, so while will terminate */
while ((gcdY & 1) == 0)
/* Loop X */
gcdY >>= 1;
/*
* Now gcdX and gcdY are both odd. Swap if necessary so gcdX <= gcdY,
* then set gcdY = gcdY - gcdX (which is even). For bignums, the
* swapping is just pointer movement, and the subtraction
* can be done in-place.
*/
if (gcdX > gcdY)
{
final int t = gcdY;
gcdY = gcdX;
gcdX = t;
} // Swap gcdX and gcdY.
gcdY = gcdY - gcdX; // Here gcdY >= gcdX.
}while (gcdY != 0);
/* Restore common factors of 2 */
return gcdX << shift;
}
private static int gcdMemoised(int x, int y)
{
if (x == 0)
return y;
if (y == 0)
return x;
int gcdX = Math.abs(x);
int gcdY = Math.abs(y);
if (gcdX == 1 || gcdY == 1)
return 1;
final List<Pair<Integer>> newPairs = new ArrayList<>();
while (gcdX != gcdY)
{
final Pair<Integer> pair = new Pair<>(gcdX, gcdY);
final Integer result = STORAGE.get(pair);
if (result != null)
{
addNewPairs(newPairs, result);
return result;
}
else
newPairs.add(pair);
if (gcdX > gcdY)
gcdX -= gcdY;
else
gcdY -= gcdX;
}
addNewPairs(newPairs, gcdX);
return gcdX;
}
So is there a way of making this algorithm faster or is the original version the fastest I'm going to get? No suggestions of using another language please, I'm looking for an algorithm improvement. Clearly my memoisation attempt was an utter failure, but maybe someone here can see a flaw/improve on it.
You can use Euclid's algorithm. It is very simple to implement and it is more efficient. Here is a code for it:
static int gcd(int a, int b) {
while (b != 0) {
int t = a;
a = b;
b = t % b;
}
return a;
}
The time complexity is O(log(A + B)), while the algorithms you are using are O(A + B). It scales better and is efficient for small a and b, too.
Here is what I came up with, on the same lines as #ILoveCoding
public static long gcd(long first, long second) {
long big = 0;
long small = 0;
if(first > second) {
big=first;
small=second;
}
else {
big=second;
small=first;
}
long temp = big % small;
while( (temp) > 1 ) {
big = small;
small = temp;
temp = big % small;
}
if( temp == 0 ) {
return small ;
}
else if( temp == 1) {
return 1;
}
else {
return -1; // will never occur. hack for compilation error.
}
}
Edit: Test cases !
System.out.println( gcd(10L, 5L));
System.out.println( gcd(11L, 7L));
System.out.println( gcd(15L, 21L));
System.out.println( gcd(-2L, -5L));
System.out.println( gcd(-2L, 2L));
Euclidean Algorithm used by author of the question (subtraction-based version) and accepted answer (mod-based) both seems to be quite not as efficient as Binary GCD Algorithm, so here it's code in java (taken from wikipidea)
static long gcd(long u, long v) {
int shift;
if (u == 0) return v;
if (v == 0) return u;
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
u >>= 1;
v >>= 1;
}
while ((u & 1) == 0) {
u >>= 1;
}
do {
while ((v & 1) == 0) {
v >>= 1;
}
if (u > v) {
long t = v;
v = u;
u = t;
}
v = v - u;
} while (v != 0);
return u << shift;
}
However, Binary algorithm is not the fastest gcd algorithm. More here.
Use Euclidean Algorithm for GCD
The algorithm is based on below facts.
If we subtract smaller number from larger (we reduce larger number),
GCD doesn’t change. So if we keep subtracting repeatedly the larger
of two, we end up with GCD.
Now instead of subtraction, if we divide smaller number, the
algorithm stops when we find remainder 0.
Code:
import java.util.*;
import java.lang.*;
class GFG
{
public static int gcd(int a, int b)
{
if (a == 0)
return b;
return gcd(b%a, a);
}
public static void main(String[] args)
{
int a = 10, b = 15, g;
g = gcd(a, b);
System.out.println("GCD(" + a + " , " + b+ ") = " + g);
}
}
Time Complexity: O(Log min(a, b))

Categories

Resources