Java Recursive Binomial Coeffecients using Linked Lists - java

There is a challenge problem in my compsci UIL class to use tail recursion to get a list of binomial coefficients for a given number . I think I am pretty close but I am having a hard time with base cases.
Following is my Code :
public static Cons binomial(int n)
{
return binomialb(n, null, 1);
}
public static Cons binomialb(int n, Cons last, int power)
{
if(n == power || n < 0)
{
return cons(1, null);
}
else if(last == null)
{
last = cons(1, cons(1, null));
return binomialb(n-1, last, power);
}
else
{
Cons lst = cons(1, null);
while(rest(last)!=null)
{
lst = cons((Integer)first(last)+(Integer)first(rest(last)), lst);
last = rest(last);
}
return binomialb(n-1,lst,power);
}
}
Right now I just get a list of (1).....

Your recursive call is always binomialb(n-1,something,power), so the only things that change are the first parameter, n, and the list. Your initial call has power = 1, so that will remain forever so. Now your first condition is
if (n == power || n < 0) {
return cons(1,null);
}
If you call it with n > 1 initially, the calls become binomialb(n-k,...,1) for k = 1, ..., n-1. Finally the call is binomialb(1,lotsOfWastedWork,1) which will happily return cons(1,null). If you initially call it with n < 1, the n < 0 will make it return the same after at most one recursive call, n = 1 immediately returns cons(1,null).
Whenever last is not null in a call, you should use it.

Related

Object oriented programming comparing linkedlists

I have objects of class Bit which is basically a class that has one field called value and it's boolean.
public class Bit {
private boolean value;
public Bit() {
this.value = false;
}
public Bit(boolean value) {
this.value = value;
}
public boolean getValue() {
return value;
}
}
and it has some more methods.
and then I have a class called number which is supposed to represent large number in their binary representation using a linked list where the firstlink is the LSB and the lastlink is the MSB.
for instance if I call the constructor
Number num1 = new Number(6);
then I'll have a linked list like the following : 0 1 1 (null)
Now I wanna know how to be able to compare two Number objects.
so for example: if I have num1, and Number num2 = new Number (7); [ 1 1 1 ]
then I want a method to tell me that num2 is larger than num1
to compare two binary numbers simply I would start with the MSB and compare each bit and once one is larger than the other that means the number is larger.
I could easily get the integer value of each Link(Bit) using Bit.toInt();
So I was thinking of iterating over the list and comparing the bits one by one , problem is that my iterator stars before firstlink (LSB) , I know I could move it all the way to the end and start iterating using hasPrevious() but I don't have that method.
I wanna be able to do that while only going over each list once.
Any ideas?
public static boolean lessEq(Number num1, Number num2){
Iterator<Bit> it1 = num1.bitIterator().;
Iterator<Bit> it2 = num2.bitIterator();
}
Number constructors:
public Number(){
list = new LinkedList<Bit>();
list.add(new Bit(false));
}
/**
* Constructs a new Number from an int.
* #param number an int representing a decimal number
*/
public Number(int number) { // assignment #1
list = new LinkedList<Bit>();
if(number == 0) list.add(new Bit(false));
if (number < 0) throw new IllegalArgumentException("number cannot be negative");
else {
while (number > 0) {
if (number % 2 == 0) {
list.add(new Bit(false));
}else list.add(new Bit(true));
number = number / 2;
}
}
}
Edit: it Works Thanks very much for the comments !
Initially you assume that both numbers are equal.
You get bits from both numbers. Use zero if either was exhausted.
If both bits are equal, you don't alter the result.
If bit from number A is 1, then set number A to be larger.
If bit from number B is 1, then set number B to be larger.
If both lists are exhausted, return result.
Otherwise repeat from step 2.
This takes into account the case where you allow lists with unnecessary zero bits as MSB.
If you want to submit fancy homework you can start from the end, keep track of the index you're at and stop at the first comparison where the bits are not equal.
You can do an obvious thing: collect the bits in an array, then walk the two arrays backwards. Or, you can use recursion, and use the stack for storage:
public int compareTo(Number other) {
Iterator<Bit> it1 = this.bitIterator();
Iterator<Bit> it2 = other.bitIterator();
return bitCompareTo(it1, it2);
}
private static int bitCompareTo(Iterator<Bit> it1, Iterator<Bit> it2) {
if (!it1.hasNext() && !it2.hasNext()) return 0;
boolean b1 = it1.hasNext() ? it1.next().getValue() : false;
boolean b2 = it2.hasNext() ? it2.next().getValue() : false;
int cmp = bitCompareTo(it1, it2);
if (cmp != 0) return cmp;
else return Boolean.compare(b1, b2);
}
This traverses each iterator only once, but since the comparison logic is after the recursive call, you get the comparisons done as they are popped off the call stack - in reverse order, just like we want them.
Basically: If we reach the end of both iterators at the same time, we're undecided on length alone, and signal that with 0, and we kick off our recursive decision-making. (If we reach the end of one iterator sooner, we assume false to left-pad that number with zeroes.) In each recursive step, if we've decided (whether on length or on a higher bit pair), we just pass that decision along. If the higher bits were undecided, we try to compare the current bit pair (and if it's equal, Boolean.compareTo will return 0, telling the next level down that we're still undecided). If we inspected all bits and we're still undecided, we'll just say 0 now stands for "equal" - precisely what compareTo should return in that case.
Once you have compareTo, it is trivial to define the other relational operators.
I think you should try this:
public static boolean lessEq(Number num1, Number num2) {
LinkedList<Bit> bits1 = num1.list;
LinkedList<Bit> bits2 = num2.list;
if(bits1.size() == bits2.size()) {
for(int i = bits1.size() - 1; i >= 0; i++) { // reversed loop since the MSB is at the end of the list
Bit bit1 = bits1.get(i);
Bit bit2 = bits2.get(i);
if(bit1.getValue() != bit2.getValue()) {
if(bit1.getValue()){ // can be replaced with return !bit1.getValue() if you want
return false; // bit1's actual bit is true, bit2 is false, so bit1 is greater
} else {
return true;
}
}
}
return true; // all bits are the same
} else {
if(bits1.size() > bits2.size()) { // can be replaced with return bits1.size() <= bits2.size() if you want
return false; // first number has more elements, so it's greater
} else {
return true;
}
}
}
EDIT
According to comments you can do the following instead (using iterators)
public static boolean lessEq(Number num1, Number num2) {
Iterator<Bit> bits1 = num1.list.descendingIterator();
Iterator<Bit> bits2 = num2.list.descendingIterator();
while(bits1.hasNext() && bits2.hasNext()){
Bit bit1 = bits1.next();
Bit bit2 = bits2.next();
if(bit1.getValue() != bit2.getValue()) {
return !bit1.getValue();
}
}
return bits2.hasNext();
}
There’s no real problem in comparing from the least significant bit. You just need to keep track of the difference found so far, and discard it if you find a difference on a higher-order (more significant) bit. It’s easiest to do it recursively:
public class Number implements Comparable<Number> {
/** Linked list of bits, least significant bit first */
Node lsb;
public Number(int n) {
if (n < 0) {
throw new IllegalArgumentException("Negative numbers not supported, got " + n);
}
if (n == 0) {
lsb = null;
} else {
lsb = new Node(new Bit(n % 2 != 0));
n /= 2;
Node tail = lsb;
while (n > 0) {
Node newNode = new Node(new Bit(n % 2 != 0));
n /= 2;
tail.setNext(newNode);
tail = newNode;
}
}
}
#Override
public int compareTo(Number other) {
return compare(lsb, other.lsb, 0);
}
private int compare(Node left, Node right, int diffSoFar) {
if (left == null) {
if (nonZero(right)) {
return -1;
} else {
return diffSoFar;
}
}
if (right == null) {
if (nonZero(left)) {
return 1;
} else {
return diffSoFar;
}
}
int localDiff = Boolean.compare(left.getData().getValue(), right.getData().getValue());
if (localDiff != 0) {
diffSoFar = localDiff;
}
return compare(left.getNext(), right.getNext(), diffSoFar);
}
private boolean nonZero(Node list) {
if (list == null) {
return false;
}
if (list.getData().getValue()) {
return true;
}
return nonZero(list.getNext());
}
}
Example use:
Number six = new Number(6);
Number seven = new Number(7);
System.out.println("Comparing 6 and 7: " + six.compareTo(seven));
System.out.println("Comparing 15 and 6: " + new Number(15).compareTo(six));
Output:
Comparing 6 and 7: -1
Comparing 15 and 6: 1
I am assuming the following Node class:
public class Node {
private Node next;
private Bit data;
// Constructor, getters, setters
}

Recursively finding the average of even numbers in an array

I'm trying to find the average of all even numbers in an array using recursion and I'm stuck.
I realize that n will have to be decremented for each odd number so I divide by the correct value, but I can't wrap my mind around how to do so with recursion.
I don't understand how to keep track of n as I go, considering it will just revert when I return.
Is there a way I'm missing to keep track of n, or am I looking at this the wrong way entirely?
EDIT: I should have specified, I need to use recursion specifically. It's an assignment.
public static int getEvenAverage(int[] A, int i, int n)
{
// first element
if (i == 0)
if (A[i] % 2 == 0)
return A[0];
else
return 0;
// last element
if (i == n - 1)
{
if (A[i] % 2 == 0)
return (A[i] + getEvenAverage(A, i - 1, n)) / n;
else
return (0 + getEvenAverage(A, i - 1, n)) / n;
}
if (A[i] % 2 == 0)
return A[i] + getEvenAverage(A, i - 1, n);
else
return 0 + getEvenAverage(A, i - 1, n);
}
In order to keep track of the number of even numbers you have encountered so far, just pass an extra parameter.
Moreover, you can also pass an extra parameter for the sum of even numbers and when you hit the base case you can return the average, that is, sum of even numbers divided by their count.
One more thing, your code has two base cases for the first as well as last element which is unneeded.
You can either go decrementing n ( start from size of array and go till the first element ), or
You can go incrementing i starting from 0 till you reach size of array, that is, n.
Here, is something I tried.
public static int getEvenAvg(int[] a, int n, int ct, int sum) {
if (n == -1) {
//make sure you handle the case
//when count of even numbers is zero
//otherwise you'll get Runtime Error.
return sum/ct;
}
if (a[n]%2 == 0) {
ct++;
sum+=a[n];
}
return getEvenAvg(a, n - 1, ct, sum);
}
You can call the function like this getEvenAvg(a, size_of_array - 1, 0, 0);
Example
When dealing with recursive operations, it's often useful to start with the terminating conditions. So what are our terminating conditions here?
There are no more elements to process:
if (index >= a.length) {
// To avoid divide-by-zero
return count == 0 ? 0 : sum / count;
}
... okay, now how do we reduce the number of elements to process? We should probably increment index?
index++;
... oh, but only when going to the next level:
getEvenAverage(elements, index++, sum, count);
Well, we're also going to have to add to sum and count, right?
sum += a[index];
count++;
.... except, only if the element is even:
if (a[index] % 2 == 0) {
sum += a[index];
count++;
}
... and that's about it:
static int getEvenAverage(int[] elements, int index, int sum, int count) {
if (index >= a.length) {
// To avoid divide-by-zero
return count == 0 ? 0 : sum / count;
}
if (a[index] % 2 == 0) {
sum += a[index];
count++;
}
return getEvenAverage(elements, index + 1, sum, count);
}
... although you likely want a wrapper function to make calling it prettier:
static int getEvenAverage(int[] elements) {
return getEvenAverage(elements, 0, 0, 0);
}
Java is not a good language for this kind of thing but here we go:
public class EvenAverageCalculation {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7,8,9,10};
System.out.println(getEvenAverage(array));
}
public static double getEvenAverage(int[] values) {
return getEvenAverage(values, 0, 0);
}
private static double getEvenAverage(int[] values, double currentAverage, int nrEvenValues) {
if (values.length == 0) {
return currentAverage;
}
int head = values[0];
int[] tail = new int[values.length - 1];
System.arraycopy(values, 1, tail, 0, tail.length);
if (head % 2 != 0) {
return getEvenAverage(tail, currentAverage, nrEvenValues);
}
double newAverage = currentAverage * nrEvenValues + head;
nrEvenValues++;
newAverage = newAverage / nrEvenValues;
return getEvenAverage(tail, newAverage, nrEvenValues);
}
}
You pass the current average and the number of even elements so far to each the recursive call. The new average is calculated by multiplying the average again with the number of elements so far, add the new single value and divide it by the new number of elements before passing it to the next recursive call.
The way of recreating new arrays for each recursive call is the part that is not that good with Java. There are other languages that have syntax for splitting head and tail of an array which comes with a much smaller memory footprint as well (each recursive call leads to the creation of a new int-array with n-1 elements). But the way I implemented that is the classical way of functional programming (at least how I learned it in 1994 when I had similar assignments with the programming language Gofer ;-)
Explanation
The difficulties here are that you need to memorize two values:
the amount of even numbers and
the total value accumulated by the even numbers.
And you need to return a final value for an average.
This means that you need to memorize three values at once while only being able to return one element.
Outline
For a clean design you need some kind of container that holds those intermediate results, for example a class like this:
public class Results {
public int totalValueOfEvens;
public int amountOfEvens;
public double getAverage() {
return totalValueOfEvens + 0.0 / amountOfEvens;
}
}
Of course you could also use something like an int[] with two entries.
After that the recursion is very simple. You just need to recursively traverse the array, like:
public void method(int[] values, int index) {
// Abort if last element
if (index == values.length - 1) {
return;
}
method(array, index + 1);
}
And while doing so, update the container with the current values.
Collecting backwards
When collecting backwards you need to store all information in the return value.
As you have multiple things to remember, you should use a container as return type (Results or a 2-entry int[]). Then simply traverse to the end, collect and return.
Here is how it could look like:
public static Results getEvenAverage(int[] values, int curIndex) {
// Traverse to the end
if (curIndex != values.length - 1) {
results = getEvenAverage(values, curIndex + 1);
}
// Update container
int myValue = values[curIndex];
// Whether this element contributes
if (myValue % 2 == 0) {
// Update the result container
results.totalValueOfEvens += myValue;
results.amountOfEvens++;
}
// Return accumulated results
return results;
}
Collecting forwards
The advantage of this method is that the caller does not need to call results.getAverage() by himself. You store the information in the parameters and thus be able to freely choose the return type.
We get our current value and update the container. Then we call the next element and pass him the current container.
After the last element was called, the information saved in the container is final. We now simply need to end the recursion and return to the first element. When again visiting the first element, it will compute the final output based on the information in the container and return.
public static double getEvenAverage(int[] values, int curIndex, Results results) {
// First element in recursion
if (curIndex == 0) {
// Setup the result container
results = new Results();
}
int myValue = values[curIndex];
// Whether this element contributes
if (myValue % 2 == 0) {
// Update the result container
results.totalValueOfEvens += myValue;
results.amountOfEvens++;
}
int returnValue = 0;
// Not the last element in recursion
if (curIndex != values.length - 1) {
getEvenAverage(values, curIndex + 1, results);
}
// Return current intermediate average,
// which is the correct result if current element
// is the first of the recursion
return results.getAverage();
}
Usage by end-user
The backward method is used like:
Results results = getEvenAverage(values, 0);
double average results.getAverage();
Whereas the forward method is used like:
double average = getEvenAverage(values, 0, null);
Of course you can hide that from the user using a helper method:
public double computeEvenAverageBackward(int[] values) {
return getEvenAverage(values, 0).getAverage();
}
public double computeEvenAverageForward(int[] values) {
return getEvenAverage(values, 0, null);
}
Then, for the end-user, it is just this call:
double average = computeEvenAverageBackward(values);
Here's another variant, which uses a (moderately) well known recurrence relationship for averages:
avg0 = 0
avgn = avgn-1 + (xn - avgn-1) / n
where avgn refers to the average of n observations, and xn is the nth observation.
This leads to:
/*
* a is the array of values to process
* i is the current index under consideration
* n is a counter which is incremented only if the current value gets used
* avg is the running average
*/
private static double getEvenAverage(int[] a, int i, int n, double avg) {
if (i >= a.length) {
return avg;
}
if (a[i] % 2 == 0) { // only do updates for even values
avg += (a[i] - avg) / n; // calculate delta and update the average
n += 1;
}
return getEvenAverage(a, i + 1, n, avg);
}
which can be invoked using the following front-end method to protect users from needing to know about the parameter initialization:
public static double getEvenAverage(int[] a) {
return getEvenAverage(a, 0, 1, 0.0);
}
And now for a completely different approach.
This one draws on the fact that if you have two averages, avg1 based on n1 observations and avg2 based on n2 observations, you can combine them to produce a pooled average:
avgpooled = (n1 * avg1 + n2 * avg2) / (n1 + n2).
The only issue here is that the recursive function should return two values, the average and the number of observations on which that average is based. In many other languages, that's not a problem. In Java, it requires some hackery in the form of a trivial, albeit slightly annoying, helper class:
// private helper class because Java doesn't allow multiple returns
private static class Pair {
public double avg;
public int n;
public Pair(double avg, int n) {
super();
this.avg = avg;
this.n = n;
}
}
Applying a divide and conquer strategy yields the following recursion:
private static Pair getEvenAverage(int[] a, int first, int last) {
if (first == last) {
if (a[first] % 2 == 0) {
return new Pair(a[first], 1);
}
} else {
int mid = (first + last) / 2;
Pair p1 = getEvenAverage(a, first, mid);
Pair p2 = getEvenAverage(a, mid + 1, last);
int total = p1.n + p2.n;
if (total > 0) {
return new Pair((p1.n * p1.avg + p2.n * p2.avg) / total, total);
}
}
return new Pair(0.0, 0);
}
We can deal with empty arrays, protect the end-user from having to know about the book-keeping arguments, and return just the average by using the following public front-end:
public static double getEvenAverage(int[] a) {
return a.length > 0 ? getEvenAverage(a, 0, a.length - 1).avg : 0.0;
}
This solution has the benefit of O(log n) stack growth for an array of n items, versus O(n) for the various other solutions that have been proposed. As a result, it can deal with much larger arrays without fear of a stack overflow.

Divisors inside an array

I need to write a method that takes an array of integers and checks for every element if all its divisors (except the number itself and 1) are present in this array. If yes, the method will return true.
For example, the following array will return true:
4,5,10,2
I can't think of something efficient enough to be implemented. Could you guys help me out here?
I've been thinking to iterate through every element in the array, search for all of its divisors, put them on array, return the array and then compare to the elements in the original array.
This is a possible solution and it could work but I want to know of other possible solutions.
EDIT: Here is a code I've came up with but it is super slow. Could you guys help me optimise it a little bit?:
import java.util.Arrays;
public class Divisors {
public static void main(String[] args) {
int[] numbers = { 4, 5, 10, 2 };
boolean flag = true;
for (int num : numbers) {
if (num % 2 != 0) {
for (int subNum = 1; subNum < num / 2; num += 2) {
if(num%subNum == 0 && subNum != 1) {
if(!Arrays.asList(numbers).contains(subNum)) {
flag = false;
}
}
}
} else {
for (int subNum = 1; subNum < num / 2; num++) {
if(num%subNum == 0 && subNum != 1) {
if(!Arrays.asList(numbers).contains(subNum)) {
flag = false;
}
}
}
}
}
System.out.println("Result is: "+flag);
}
}
I think the following alogorithm solves your need. I have tested it on a few cases and it seems to work.
For example the array:
int[] set = {2, 3, 4, 5, 7, 10, 11, 15, 18, 35};
executes instantly giving the answer "true". Try removing the 7 which will give the answer "false".
You call it thus:
reduce(set, 0, 0)
The principle used is to iterative recursively through the array, reducing the array through factorization of the array by each element. If you find an element which is smaller than the last factor, it means it can't be factored. This only works if the array is sorted. Once you reach the end of the array, you know all elements have been factored.
private static boolean reduce (int[] set, int index, int factor) {
// NOTE: set must be a sorted set of integers
if (index == set.length) {
return true;
} else {
int divisor = set[index];
if (divisor != 1) {
if (divisor < factor) return false;
for (int i = index; i < set.length; i++) {
while ((set[i]%divisor) == 0) {
set[i] = set[i]/divisor;
}
}
return reduce(set, index+1, divisor);
} else {
return reduce(set, index+1, factor);
}
}
}
See if it works, let me know if you run into any problems.
1.Iterate through every element in the array
2. Find in for loop its divisor
3. While doing 2), check for every divisor if it is contained in the array. If false - return false.

Java Recursion compilation error

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);
}
:-)

How do I use a recursive algorithm to determine whether the array contains two elements that sum to a given integer?

Okay guys thanks for all the help! Special thanks to #pjs for giving me an idea of how to do it. Here is my new code, but for some reason it won't reach one of the base cases. Sorry if I deleted the old code, this is the first time I posted here and I am not sure if I should answer my own question with the new code.
//initialized int start = 0
//initialized int end = length of the array
//here goes the constructor
public boolean kPairSum(Integer k) {
if (sortedIntegerArray.length < 2) { //if array is less than two return false
return false;
}
else if (start == end) { //once the start and the end meets. This is the base case that doesn't seem to work for me.
return false;
}
else {
int currentStart = sortedIntegerArray[start]; //get first int in the array
int currentEnd = sortedIntegerArray[end-1]; //get the very last int in the array
int sum = currentStart + currentEnd; //get the sum
if (k.equals(sum)) { //compare sum and k if equal
return true;
}
else if (sum <k) { //if sum is less than k then increment value of start
start++;
return kPairSum(k);
}
else if (sum > k) { //if sum is greater than k then it decrements value of end
end--;
return kPairSum(k);
}
else { //not sure if this is right, should I just get rid of the else if statement for sum > k and change it to just an else? I wrote this down cause it has to return a type of boolean.
return kPairSum(k);
}
}
Your array is called sortedIntegerArray, but you don't seem to be leveraging that fact.
Start by summing the two ends of the array. If the sum is smaller than k, one of the two elements of the sum has to be larger. You can only get a larger value by incrementing the lower index because the elements are ordered. Similarly, if the sum is larger than k, one of the two elements has to be smaller, so you need to decrement the upper index. In either case, the structure of the problem is the same but you're now operating on a subset of the array specified by which of the indices you incremented/decremented. Base cases are that you found two values which sum to k, or that the indices have met somewhere. The recursion should leap out at you. Since each recursive call either increments or decrements a boundary index until they meet in the middle, it's O(n).
Your recursive call is never invokes:
if (sum == k) { //compare to given k
return true;
} else if (xx == sortedIntegerArray.length-1 || sum != k) {
return false;
}
Note that you basically have two choices: sum==k, and then - return true, or sum!=k - and then return false. The recursive invokation is not reachable.
An O(n) (average case) solution can be achieved using a hash table. The idea is to add each element to the hash table while iterating, and check if there is an existing element that completes to k.
for each element e in arr:
if e is in table:
return true
table.add(k-e)
return false //no pair was found that sums to k
A recursive solution that checks all pairs, is basically brute force that is similar to a nested for loop.
//i is the index we are now checking, b is a boolean indicating we have already reduced one element
kSum(k,i,b):
if i == arr.length
return false
if b == true && k == 0:
return true
if b == false:
return kSum(k-arr[i],i+1,true) || kSum(k,i+1,false)
else:
return kSum(k,i+1,b)
I have two implementations here:
One I initially got to work and with Amit answer, I improved it further. It also prints/return the indices that make up the sum. works with both sorted and unsorted array in O(n). ofcourse, this is not recursive.
public static void sumArray2(int[] arr, int sum){
Map <Integer, Integer> map = new HashMap<>();
for (int i=0; i < arr.length;i++){
map.put(arr[i], i);
}
for (int i =0; i < arr.length;i++){
int diff = sum-arr[i];
if (map.containsKey(diff) && i!=map.get(diff)) {
System.out.printf("The two indices are %s and %s%n ",i,map.get(diff));
return ;
}
}
System.out.printf("The sum:%s cannot be formed with given array:%s",sum,Arrays.toString(arr));
return ;
}
//returns a boolean if sum could be formed.
public static boolean sumArray3(int[] arr, int sum){
Map <Integer, Integer> map = new HashMap<>();
for (int i =0; i < arr.length;i++){
int diff = sum-arr[i];
if (map.containsKey(arr[i])) {
System.out.printf("The two indices are %s and %s%n ",i,map.get(arr[i]));
return true;
}
map.put(diff,i);
}
System.out.printf("The sum:%s cannot be formed with given array:%s",sum,Arrays.toString(arr));
return false;
}
don't know how to add formatted comment, so here is enhanced version, than Amit provided, works with O(n) :)
def check(source, need):
target = [need-i for i in source]
target.reverse()
i = 0
j = 0
# walk thru lists same "merge" to find a match
for i in xrange(0, len(source)):
while j < len(target) and source[i] > target[j]:
j=j+1
if i != len(source)-j-1 and j < len(target) and source[i] == target[j]:
return True
return False

Categories

Resources