I need to build a recursive function that returns true if array a is permutation of array b and false otherwise.
public static boolean isPermutation (int [] a, int [] b)
Can add arguments to the function.
Can NOT use local array.
Can NOT use loops.
Can NOT use library functions.
Can NOT change the arrays.
Does anyone have an idea?
This should work for you, it's basically a loop implemented with recursion. This should execute in quadratic time.
public static boolean isPermutation(int[] a, int[] b, boolean[] ataken, boolean[] btaken, int iter, int totalTaken, int aidx, int bidx)
{
if (a.length != b.length) return false;
// totalTaken is a count of the number of matches we've "taken"
if(totalTaken == a.length) return true;
// don't "loop" b
if(bidx >= b.length)
{
return false;
}
// we should loop through a... this will yield a quadratic runtime speed
if(aidx >= a.length)
{
if (iter < a.length)
{
return isPermutation(a, b, ataken, btaken, iter + 1, totalTaken, 0, bidx);
}
// finished our loop, and "totalTaken" wasn't the whole array
return false;
}
// found a match for this b[bidx]
if(a[aidx] == b[bidx] && !ataken[aidx] && !btaken[bidx])
{
ataken[aidx] = true;
btaken[bidx] = true;
return isPermutation(a, b, ataken, btaken, iter, totalTaken + 1, aidx + 1, bidx + 1);
}
// loop through a
return isPermutation(a, b, ataken, btaken, iter, totalTaken, aidx + 1, bidx);
}
You call it with ataken and btaken arrays filled with false, but of the same length as a and b, respectively.
var isPerm = staticClassName.isPermutation(a, b, ataken, btaken, 0, 0, 0, 0);
The idea is the following: it's a permutation if the product of all members in a is equal to the product of all members in b AND the sum of all members in a is equal to the sum of all members in b.
Write a recursive helper function that will allow you to compute these sums and products and compare them.
Complexity: O(n)
Caveat: can overflow if dealing with many large numbers
See the comments for an important point made by John Carpenter
Related
I'm writing a recursive program:
public static List<Integer> method(int n)
to determine whether a positive number n is the total of cubes that are positive (> 0). Example: given n = 1944 (12^3 + 6^3), the program would return the list [12, 6] in descending order. If n is not the total of cubes the program should return an empty list.
The program should return the values that start with the highest possible value for the first element, and then follow the same rule for the rest of the elements. For example, when n = 1072, the program would return [10, 4, 2] instead of [9, 7].
The method where the recursion should occur:
private static boolean method(int n, int c, LinkedList<Integer> seen)
where c is the highest number that is still allowed to be used and soFar is the list of numbers that have already been seen.
My code covers the base cases and the recursion, but I'm having issues with the loop continuing. With the input, n = 1944 my program is returning the list [12] instead of [12, 6].
public static List<Integer> method(int n)
{
LinkedList<Integer> result = new LinkedList<Integer>();
int c = (int) Math.cbrt(n);
result.add(c);
method(n, c, result);
return result;
}
private static boolean method(int n, int c, LinkedList<Integer> seen)
{
LinkedList<Integer> result = new LinkedList<Integer>();
boolean b = false;
if (n == 0)
{
return true;
}
else if (c == 0)
{
return false;
}
else
{
int sum = 0;
for (int i : seen)
{
sum += i*i*i;
}
while (b = false)
{
c = (int) Math.cbrt(n - sum);
seen.add(c);
method(n, c, seen);
if (sum == n)
{
result = seen;
return true;
}
else
{
return false;
}
}
}
return false;
}
Let's see your while loop:
LinkedList<Integer> result = new LinkedList<Integer>();
boolean b = false;
// Some code omitted here.
while (b = false)
{
c = (int) Math.cbrt(n - sum);
seen.add(c);
method(n, c, seen);
if (sum == n)
{
result = seen;
return true;
}
else
{
return false;
}
}
First, with a while loop that always has false as the condition for looping, it doesn't do anything at all.
Anyway, even if we pretend the loop runs, whatever is the branch took by the if, a return will be reached. So, your while loop doesn't loop at all even if its condition was changed to always be true. Further, the only value ever assigned for the b variable is false, and it isn't used for anything at all.
Also, the result list in the second method is always empty. And, since the result = seen; instruction is just right before the return, it is an innocuous instruction which renders the result simply being useless.
Also, look at the method(n, c, seen); call. It don't do anything with its return value! So, even if it eventually returns true, you still proceeds, which would then generate false as a result.
Also, whenever you add a value to seen, it will never be removed. Since the seen is always the very same list in every of the recursive method calls, once a bad number is added there, it will never be removed to make the way for something else.
With this, I must conclude that your algorithm is so broken that it must be rewritten from scratch.
Also, although your question isn't very clear, I presume that the numbers found must all be different. Otherwise, one could make 2 = 13 + 13 and every number larger than one could be represented by the sum of a lot of cubed ones (i.e. n = 13 + 13 + 13 + ...).
The algorithm is this:
The first step is to have a for counting i down from cbrt(n) to 1 trying to form cubes.
Then, subtract the cube from n and recursively try to find a cube sum for the resulting number.
Add a parameter to avoid repeating numbers, which is one smaller than the last number used.
When a cube is formed, return the number that formed it. In the outer calls, add the result to the list of non-empty inner recursive call.
If an inner recursive call gives an empty list as a result, then the current iteration of the for produced a bad number and we should try the next one (if we have a next one).
If the for ends without a cube forming, return an empty list.
Here is the code:
import java.util.LinkedList;
import java.util.List;
public class Main {
public static List<Integer> findCubeSum(int n) {
return findCubeSum(n, n);
}
public static List<Integer> findCubeSum(int n, int max) {
if (n <= 0) return List.of();
int c = (int) Math.cbrt(n);
for (int i = Math.min(c, max); i > 0; i--) {
int x = i * i * i;
if (x == n) {
List<Integer> result = new LinkedList<>();
result.add(i);
return result;
}
List<Integer> result = findCubeSum(n - x, i - 1);
if (result.isEmpty()) continue;
result.add(0, i);
return result;
}
return List.of();
}
public static void main(String[] args) {
System.out.println(findCubeSum(8)); // [2]
System.out.println(findCubeSum(64)); // [4]
System.out.println(findCubeSum(1000)); // [10]
System.out.println(findCubeSum(1072)); // [10, 4, 2]
System.out.println(findCubeSum(1944)); // [12, 6]
System.out.println(findCubeSum(4)); // []
System.out.println(findCubeSum(0)); // []
System.out.println(findCubeSum(-1)); // []
System.out.println(findCubeSum(10)); // []
}
}
See it running at ideone.
The code as posted has many issues. However your question is about public static List<Integer> method(int n):
public static List<Integer> method(int n) {
LinkedList<Integer> seen = new LinkedList<>();
method(n, 0, seen);
return seen;
}
Consider changing
private static boolean method(int n, int c, LinkedList<Integer> seen)
To
private static boolean method(int n, LinkedList<Integer> seen)
because you recalculate the value of c by c = (int) Math.cbrt(n);
i have a problem with an exam test.
I have two arrays: int[] a, int[] b, with random values.
E1 return true if there are two elements of b greater then each element of a.
How do I write "there are two elements of b greater than each element of a"?
I can write "there is ONE elements of b greater than each element of a" in this way:
public static boolean e1(int[] a, int[] b){
boolean ris = false;
boolean ogniA = true;
int i = 0;
if(a != null && a.length != 0){
while(ogniA && i<a.length){
boolean es1= false;
boolean es2 = false;
int j = 0;
if(b!= null && b.length != 0){
while(!es1 && j < b.length){
if(j%2!=0){
es1 = a[i] < b[j];
}
j++;
}ris = es1 ;
}
i++;
}
}
return ris;
I need something like this. Thanks for help.
So I would solve this problem, by dividing it into smaller problems.
1st you need to find the 2 biggest values in the first array.
I presume this should be abstract and work for every array
Code (using the example from Andronicus):
"E1 return true if there are two elements of b greater then each element of a"
Basically you need the second greater value of array B and the greater value of the array A
int[] a = {3, 5, 7, 9};
int[] b = {2, 4, 3, 10, 11};
int secondGreatestOfB = IntStream.of(b).boxed()
.sorted(Comparator.reverseOrder())
.limit(2)
.sorted(Comparator.naturalOrder())
.limit(1)
.findFirst().orElse(0);
System.out.println(areTheTwoBiggestNumbersOfArrayBbiggerThanAllValuesFromArrayA(a, secondGreatestOfB));
private static boolean areTheTwoBiggestNumbersOfArrayBbiggerThanAllValuesFromArrayA(int[] a, int secondGreatestOfArrayB) {
return secondGreatestOfArrayB > IntStream.of(a).max().orElse(0);
}
How would you solve the following task:
Write a recursive method which gets passed an array, filters all odd numbers and store them into an array. The returned array has to be sorted by each elements order.
You are not allowed to use any provided methods by java classes like Arrays.sort, Lists, etc. Furthermore loops are disallowed and generic well known sort algorithm applied to the result as well.
The part of filtering is easy, but I don't know how to put each element at its right place. At the moment my method only returns an unsorted array with all odd numbers.
public static int[] filterOdd(int[] m){
return filterOdd(m, 0, 0);
}
private static int[] filterOdd(int[] m, int idx, int idxToPlace){
if(idx <= m.length -1){
if(m[idx] % 2 == 0){
return filterOdd(m, idx + 1, idxToPlace);
}else{
int[] buffer = filterOdd(m, idx + 1, idxToPlace + 1);
buffer[idxToPlace] = m[idx];
return buffer;
}
}else{
return new int[numberOfOddIntegers(m)];
}
}
Is there any way to insert the odd number at its right place recursively?
At the place where you do buffer[idxToPlace] = m[idx]; you have to call another method that will return the sorted array with the current processing number added to it.
That new method can be recursive too: you know at that moment that the array you have in your hands is ordered. You just recursively traverse (for example from the end to the begin) and from the moment your element fits in (e.g. is smaller than the previous element) you can insert it and return the sorted array. If there is only 1 element (base case) you can just return it.
That way, at the end of your algorithm, the list will be sorted.
I'm not allowed to use System.arraycopy
This means that you need to figure out how many odd numbers you are going to have, in order to size your result properly:
public static int[] filterOdd(int[] m){
int[] res = new int[countOdd(m, 0)];
filterOdd(m, 0, 0, res);
return res;
}
private static int countOdd(int[] m, int i) {
if (i == m.length) {
return 0;
}
int isOdd = m[i] % 2 != 0 ? 1 : 0;
return isOdd + countOdd(m, i+1);
}
private static void filterOdd(int[] m, int src, int dest, int[] res){
if(src == m.length) {
return;
}
if (m[src] % 2 != 0) {
res[dest++] = m[src];
}
filterOdd(m, src+1, dest, res);
}
Here's my problem:
Write a method called allLess that accepts two arrays of integers and returns true if each element in the first array is less than the element at the same index in the second array. Your method should return false if the arrays are not the same length.
Here is my test data:
int[] arr1 = {1,2,4};
int[] arr2 = {3};
int[] arr3 = {5,4,6};
int[] arr4 = {2,2,7};
int[] arr5 = {2,3,6,8};
System.out.println(allLess(arr1,arr2)); //should print false
System.out.println(allLess(arr1,arr3)); //should print true
System.out.println(allLess(arr1,arr4)); //should print false
This is the code I have so far:
public static boolean allLess(int[] a, int[] b){
int len1=a.length;
int len2=b.length;
if(len1==len2){
for(int i=0; i<len1;i++)
if(a[i]<b[i])
return true;
}
else if(len1 !=len2)
return false;
return false;
}
However, when I try System.out.println(allLess(arr1,arr4)); it's printing true. How do I fix this?
The crux: you should scan until you find a mismatch. You're currently only looking for the first happy case.
The main part that you need to change is your conditional - flip its condition.
if(a[i] >= b[i]) {
return false;
}
Be sure to change your last return to true as you've exhausted all negative conditions, and you're pretty much good to go.
There's more cleanup that should be done here, since we're looking at it.
First, use braces everywhere. Do so and your code will be a fair bit easier to follow. You also won't run into bugs if you suddenly discover you need to add more to a conditional block without braces.
Next, you don't need to declare more variables for the length of the arrays - you only care about them in two spots. Just reference a.length and b.length directly as it's not a method call; it's a field, which costs nothing to access.
Third, your else if condition is redundant; it should be an else. Either the lengths of the arrays are equal or they're not.
Here's what it might look like overall:
public static boolean allLess(int[] a, int[] b) {
if (a.length == b.length) {
for (int i = 0; i < a.length; i++) {
if (a[i] >= b[i]) {
return false;
}
}
} else {
return false;
}
return true;
}
Simplifications to this basic form exist.
If you were interested in a Java 8-centric approach, then you could consider this methodology with streams. Essentially, we want to scan all of your elements, and reject the entire statement if the length of the arrays are not equal AND if the value in ai is not equal to bi.
public static boolean allLess(int[] a, int[] b) {
return a.length == b.length && IntStream.range(0, a.length)
.allMatch(i -> a[i] < b[i]);
}
The if statement is returning early, you need to invert the logic and return:
if(a[i]>=b[i])
return false;
This code only compares the first two elements of the arrays. You could instead try the following:
public static boolean allLess(int[] a, int[] b){
int len1=a.length;
int len2=b.length;
if(len1==len2){
for(int i=0; i<len1;i++)
if(!(a[i]<b[i]))
return false;
}
else if(len1 !=len2)
return false;
return true;
}
I am a fresh student in computer science and currently we study Java recursion. Unfortunately, the academy only explains the following regarding this topic:
What recursion means.
There are 2 types of cases when using a recursive algorithm: base cases and recursive cases and their purpose.
An example of factorial and Fibonacci implementation using recursion.
Now I got the following exercise:
Two integer numbers will be called "strangers" if their greatest common divisor (aka GTC) is ONLY 1". For example, the numbers 8 and 9 are "strangers" because their GTC is 1. However, 8 and 9 are not "strangers" because their GTC is 2.
Please implement a recursive method which receives an array of integers, and returns "true" if every pair numbers in this array are strangers, and "false" otherwise.
Method signature must be as follows:
public boolean checkGCD(int[] values)
For example:
{3, 5, 7, 11} -> method will returns true.
{4, 7, 8, 9} -> method will returns false because 4 and 8 are not strangers.
For assistance, you can use the following method for finding GTC (Euclidean algorithm):
private static int gcd(int n, int m){
if (m==0)
return n;
return gcd(m,n % m);
}
In addition, the method checkGCD(int[] values) should be overloaded...
Loops cannot be used!
The above can be done very easily with a nested loop, but I must use recursion!
I understand that I need to use an overloaded method which gets the array, lo index and hi index.
So this is what I came up in mind:
######
Base case: if there is at least one pair of numbers in the array which are not strangers, method returns false (no need to continue the comparison...).
######
Comparison will be done in the following way: lo index points to the 1st cell -> hi index points to the 2nd cell -> comparing -> hi index is incremented by 1 until it reaches the last cell of the array.
Then, lo index is incremented by 1, and then repeating the above.
So bottom line, I should compare the first cell to all consecutive cells, compare the 2nd to all consecutive cells, the 3rd etc...
########
If all pairs of numbers are strangers, I need something else to stop recursion. Therefore, if all pairs are strangers, it means that lo index and hi index will eventually point to the last cell (cause both lo and hi index has incremented gradually, and they reach the last array cell after all comparisons turned out to be OK i.e strangers).
The following is the overloaded function:
private static boolean checkGCD(int[] values, int lo, int hi)
{
if ( (gcd(values[lo], values[hi]) )!= 1 )
return false;
else if (lo < values.length-1 && hi < values.length-1)
return checkGCD(values, lo, hi+1);
else if (lo < values.length-2 && hi == values.length-1)
return checkGCD (values, lo+1, lo+2);
if (lo == values.length-1 && hi == values.length-1)
return true;
} -> Compiler says "missing return statement"**
The following is the method the exercise requires to have, and it basically just calls the overloaded method which does everything recursively.
public static boolean checkGCD(int[] values)
{
return checkGCD(values, 0, 1);
}
When I try to compile, I get "missing return statement" which points to the close bracket in the overloaded function
But I do use "return" in the overloaded function.
Please clarify how to fix. I am sure after compilation error, the above overloaded function is still not OK.
You get the compiler error because, if every if fails, the method does not return anything. The solution is add the appropriate return statement when the final if fails.
Not to give the answer away, but here's a strong hint: the base case is an array with two elements. All larger arrays are recursive cases.
There's a general pattern for going through a list with a recursion (pseudocode):
Result f(List f) {
if(f is an empty list) {
return Result for an empty list;
} else {
return (Result for head of list) merged with f(tail of list)
}
}
Since you're using arrays, rather than a type with convenient head() and tail() methods, you could pass in an index to say how much of the array you want to process. When index == array.length you are processing an "empty list".
boolean allMembersPositive(int[] array, int index) {
if(index == array.length) {
return true;
} else {
return (array[index] >=0) && (allMembersPositive(index + 1));
}
}
It's a small step to adapt this to consume two array items per recursive call.
I can guarantee you that when you understand recursion clearly you are going to level up your programming skills.
I recommend reading these URLs:
http://howtoprogramwithjava.com/java-recursion/
http://danzig.jct.ac.il/java_class/recursion.html
Now, lets move back to your questions. I think that is one possible way to implement it:
public class Test {
public static void main(String[] arguments) {
int[] strangers = { 3, 5, 7, 11 };
int[] acquaintances = { 4, 7, 8, 9};
boolean verifyStrangers = checkGCD(strangers);
boolean verifyAcquaintances = checkGCD(acquaintances);
System.out.println(verifyStrangers);
System.out.println(verifyAcquaintances);
}
public static boolean checkGCD(int[] values) {
return checkGCD(values, 0, 1);
}
/*
* I'm really not sure why your professor wants this method signature: "checkGCD(int[] values, int i, int j)"
* I'm coding what I understood from the problem.
*/
private static boolean checkGCD(int[] values, int i, int j) {
boolean result = true;
if (gcd(values[i], values[j]) != 1){
result = false;
}
j++;
if (j < values.length ) {
result = result && checkGCD(values, i, j);
}
return result;
}
private static int gcd(int n, int m) {
if (m == 0)
return n;
return gcd(m, n % m);
}
}
I managed to solve the exercise.
public static int gcd(int n, int m)
{
if (m==0)
return n;
return gcd(m,n % m);
}
private static boolean checkGCD(int[] values, int lo, int hi)
{
// System.out.println("lo is " + lo + " hi is " + hi);
// System.out.println("");
// System.out.println("[lo] is " + values [lo] + " [hi] is " + values[hi]);
// System.out.println("");
if ( (gcd(values[lo], values[hi]) )!= 1 )
return false;
if (lo < values.length-1 && hi < values.length-1)
return checkGCD(values, lo, hi+1);
if (lo < values.length-2 && hi == values.length-1)
return checkGCD(values, lo+1, lo+2);
if (lo == values.length-2 && hi == values.length-1)
return true;
return true;
}
public static boolean checkGCD(int[] values)
{
return checkGCD(values, 0, 1);
}
:-)