This is the original problem:
Write a recursive, int valued method named productOfOdds that accepts an integer array and the number of elements in the array, and returns the product of the odd-valued elements of the array. You may assume the array has at least one odd-valued element. The product of the odd-valued elements of an integer-valued array recursively may be calculated as follows:
If the array has a single element and it is odd, return the value of that element; otherwise return 1.
Otherwise, if the first element of the array is odd, return the product of that element and the result of finding the product of the odd elements of the rest of the array; if the first element is NOT odd, simply return the result of finding the product of the odd elements of the rest of the array.
This is what I have and I can't figure out why it's not working:
public static int productOfOdds(int[] arr, int index)
{
if (index == 1)
{
if ((arr[0]%2) != 0)
return arr[0];
else
return 1;
}
else if ((arr[0] % 2) != 0)
return (arr[0] * productOfOdds(arr, index - 1));
else
return productOfOdds(arr, index - 1);
}
The problem is that, while you pass in your index, you don't check the array value at your index, but the array value at 0. This should fix the problem:
public static int productOfOdds(int[] arr, int index){
if (index == 1)
{
if ((arr[index-1]%2) != 0)
return arr[index-1];
else
return 1;
}
else if((arr[index-1]%2) != 0 )
return (arr[index-1] * productOfOdds(arr, index-1));
else
return productOfOdds(arr, index-1);
}
I believe for this part:
else if ((arr[0] % 2) != 0)
return (arr[0] * productOfOdds(arr, index - 1));
You meant to say:
else if ((arr[index] % 2) != 0)
return (arr[index] * productOfOdds(arr, index - 1));
By using 0 here instead of index your result will always be
1 if arr[0] is even
arr[0] if it is odd
The reason it is not working is that you never calculate anything that's not the first array element. There is nothing in your recursion that causes it to go to the second element, the third and so on.
What may be confusing is the fact the parameter that expresses the length of the array is called index. But you're treating it like length. Anyway, let's see what you are doing here:
Your end condition seems good - if the length is 1, test the only element that exists, and do as the assignment text tells you to do.
But what about the recursion step?
Suppose you have two elements and the first one is odd. Your index is 2. So you call the same function with the same array and 1. This will return the value of the element in position zero. And then you multiply it by the element at position zero. If your array was 8 elements long, it would still be multiplying by the same first element, so you basically get (arr[0])length (if it's odd) or 1 (if it's not odd).
You have two ways to solve this problem.
Go with only one parameter, but against the text of the assignment
To do this, you have to check the last element of the array. So if your array length 1, you do as you did so far. But if it's greater than 1, you have to do:
if ( arr[index-1]%2 != 0 ) {
return arr[index-1]*productOfOdds(arr,index-1);
} else {
return productOfOdds(arr,index-1);
}
Go with two parameters, but follow the letter of the assignment
To do this, you have to also pass the parameter that says where the subarray starts. That is, you check the first element of the array, but tell the recursive step to check from the second element forward. Basically, you tell your method "Look at this array as if it's starting at position startIndex rather than 0".
private static int productOfOdds(int[] arr, int startIndex, int length) {
if (length == 1) {
if ((arr[startIndex]%2) != 0)
return arr[startIndex];
else
return 1;
} else if((arr[startIndex]%2) != 0 )
return (arr[startIndex] * productOfOdds(arr, startIndex + 1, length-1));
else
return productOfOdds(arr, startIndex+1, length-1));
}
public static int productOfOdds(int[] arr, int length ) {
return productOfOdds( arr, 0, length );
}
The second method with just two parameters is there in order to follow the letter of your assignment, which was to have a method that accepts an array and its length only. Internally it works with three parameters, but to the world you present a two-parameter method (note the private vs public modifiers).
Personally, I think the first method is more elegant, despite the fact that your instructor told you to use the first element.
Related
A logic question in a MOOC I'm taking asked how one would go about returning the total number of increasing subsequences within a given int array using recursion.
In my method I use an index parameter as well as a position parameter to compare values with the index. My regular base case is when the index has reached the end of the list, and then I return 1 to account for an array of length 0 to technically count as a valid increasing subsequence. The method in the else statement I currently have written is only able to find subsequences of length 2. For example, if I have array [1, 2, 3], the method only returns 7 because it isn't counting 123. I'm not sure how to write this so as to account for longer subsequences. I believe it has something to do with creating a separate array and adding values to it and then adding its length to the final value, but I'm not sure how this would be implemented recursively.
public static int bettersubseq(int[] arr, int index, int pos) {
if (index == arr.length) {
return 1;
} else {
if (pos == index) {
return 1 + bettersubseq(arr, index + 1, 0);
} else {
if (arr[pos] < arr[index] && (pos < index)) {
return 1 + bettersubseq(arr, index,pos + 1);
} else {
return 0 + bettersubseq(arr, index, pos + 1);
}
}
}
}
Let's assume I have this array: ARR = {5, 7, 3, 3, 7, 5}
and I also have the size ( = 6 in this example ) so the recursive function should return 3.
this is the declaration of the function/method:
int f(arr, size);
I tried this thing:
count = 0;
if(size == 1)
return 1;
if(x[i] != f(arr, size-1)
count++;
return count;
but it doesn't work, as f(arr, size-1) doesn't walk through all the elements of the array and compare.
hopefully you guys could help!
Here's one way to do it:
private static int f(int[] arr, int size) {
if (size <= 1) return 0; // there can't be duplicates if there are not even 2 elements!
return f(arr, size - 1) + (inArray(arr, size - 1, arr[size - 1]) ? 1 : 0);
}
private static boolean inArray(int[] arr, int size, int elem) {
if (size == 0) return false;
return arr[size - 1] == elem || inArray(arr, size - 1, elem);
}
Basically the logic is this:
The size indicates the first N elements in arr that we actually care about.
If size is less than 2, we know there can't be any duplicates, so return 0.
Now for the recursion case, we return either 1 or 0 depending on whether the last element is in the rest of the array, plus whatever number of duplicates in the rest of the array ("the last element" means array[size - 1] and "the rest" means calling the function with size - 1.)
To determine whether an element is in an array, I used a recursive method as well, with a similar idea (check if the last element is elem, then check if the rest contains elem).
i have a problem in understanding the following:
public int sort(char[] arr, int index)
{
if(!isEmpty())
{
index = leftChild.sort(arr,index);
arr[index++] = getContent().getToken();
index = rightChild.sort(arr,index);
}
return index;
}
Why is that working but not this:
public void sort(char[] arr, int index)
{
if(!isEmpty())
{
leftChild.sort(arr,index);
arr[index++] = getContent().getToken();
rightChild.sort(arr,index);
}
}
And i also dont understand this : index = leftChild.sort(arr,index); What does this do? Can you guys pls give me examples?
Thanks for your help,
Kiimarii
One more question, i have a method that prints the longest way from the root to a leaf of the binaryTree:
public int height()
{
if ( !isEmpty() )
{
int leftHeight = leftChild.height();
int rightHeight = rightChild.height();
if ( leftHeight > rightHeight )
{
return leftHeight + 1;
} else {
return rightHeight + 1;
}
} else {
return 0;
}
}
But how can leftHeight > rightHeight be done, if no one has a value? they are both zero or something so how can he compare that? Thanks !
Your method performs an in-order traversal of a binary search tree.
The first snippet first calls leftChild.sort(arr,index), which assigns the left sub-tree to the input array. It returns the next index to be assigned.
Then you assign getContent().getToken() of the current node to the arr[index]
Then the call to rightChild.sort(arr,index) assigns the right sub-tree to the input array and the next index to be assigned is returned.
If you ignore the index returned by the recursive call (as you do in the second snippet), arr[index++] = getContent().getToken(); will always assign a value to the 0 index of the array (assuming the initial call is (sort(arr,0))).
You must assign the returned index to the local index variable in order to assign getContent().getToken() to the correct index of the array.
The key is that index is a local variable. Let's follow a really simple example:
4
/ \
2 6
/
1
// First call
(4).sort(arr, 0);
// The left child of (4) is (2)
// (Note that each 'index' here
// is a local variable.)
index = (2).sort(arr, 0);
// We've just called sort again
index = (1).sort(arr, 0)
// and again
index = (empty).sort(array, 0)
// isEmpty() is true
// so return index
return 0
<=
index = 0
// assign contents of (1) to
// arr[0] and increment 0
arr[index++] = getContent().getToken();
// Process right child of (1)
// (index returns unchanged)
index = (empty).sort(arr, 1);
return 1
<=
index = 1
...
We're now in the call to (2).sort so its contents get assigned to index 1 of the array. Can you see how the sequence will complete in order?
Java newbie is here. I'm practicing the array question, and I had problem with this question: Given an array of ints of odd length, look at the first, last, and middle values in the array and return the largest. The array length will be a least 1.
I know how to find the first,last,and middle value in an array. Then I tried to use if statement to solve this question.
My code:
public int maxTriple(int[] nums) {
if(nums[0]>nums[(nums.length+1)/2-1]&&nums[0]>nums[nums.length-1]){
return nums[0];
}else if(nums[(nums.length+1)/2-1>]>nums[0]&&nums[(nums.length+1)/2-1>]>
nums[nums.length-1]){
return nums[nums.length-1];
}else{
return nums[nums.length-1];
}
}
But this code does not work at all how can I fix my code?
In second else-if you have extra ">" (maybe it is a misspelling)
And if the second condition is true you need to return nums[(nums.length+1)/2-1
So you need to fix it in this way:
public int maxTriple(int[] nums) {
if(nums[0]>nums[(nums.length+1)/2-1]&&nums[0]>nums[nums.length-1]){
return nums[0];
}else if(nums[(nums.length+1)/2-1]>nums[0]&&nums[(nums.length+1)/2-1]>nums[nums.length-1]){
return nums[(nums.length+1)/2-1];
}else{
return nums[nums.length-1];
}
}
Since you are only interest in the value, not the index, you can use
public int maxTriple(int[] nums) {
int max = Math.max(nums[0], nums[nums.length - 1]);
return Math.max(max, nums[nums.length / 2]);
}
First, to make the code more readable/understandable, you should assign the 3 values of interest to local variables, and you should add some spaces around operators.
Also, since you know the length will be odd, length / 2 is enough to find middle value:
int first = nums[0];
int middle = nums[nums.length / 2];
int last = nums[nums.length - 1];
When your if block ends with a return statement, the else becomes redundant, though that is a matter of style. In this case it makes little difference, but in more complex code it can make a big difference to the code complexity.
And of course, your main problem, as PM 77-1 pointed out.
Are you aware that you return nums[nums.length-1] twice?
The middle return statement was returning the wrong value:
if (first > middle && first > last) {
return first;
}
if (middle > first && middle > last) {
return middle;
}
return last;
You can use the ternary conditional operator to write that in a single statement:
return (first > middle && first > last ? first :
middle > first && middle > last ? middle : last);
You can use the Math.max() method to simplify it:
return Math.max(Math.max(first, middle), last);
Or you can use IntStream.max(), which is better if you have many values:
return IntStream.of(first, middle, last).max().getAsInt();
Readable more than multiple conditions :
public int maxTriple(int[] nums) {
return Math.max(Math.max(nums[0], nums[nums.length - 1]), nums[nums.length / 2]);
}
Ok, so I've been trying to wrap my head around recursion in Java and I can accomplish easy tasks such as sum, reversing etc. but I have been struggling to do this exercise:
I'm trying to find the minimum number in an array using recursion but keep getting an answer of 0.0.
My understanding for recursion is that there I need to increment one element and then provide a base case that will end the recursion. I think I'm messing up when I have to return a value and when is best to call the recursion method.
This is what I have so far:
public static double findMin(double[] numbers, int startIndex, int endIndex) {
double min;
int currentIndex = startIndex++;
if (startIndex == endIndex)
return numbers[startIndex];
else {
min = numbers[startIndex];
if (min > numbers[currentIndex]) {
min = numbers[currentIndex];
findMin(numbers, currentIndex, endIndex);
}
return min;
}
} //findMin
Here's a simplified version:
public static double min(double[] elements, int index) {
if (index == elements.length - 1) {
return elements[index];
}
double val = min(elements, index + 1);
if (elements[index] < val)
return elements[index];
else
return val;
}
Hint: You're calling findMin recursively, but then not using its return value.
What's the relationship between (1) the min of the whole array, (2) the first element, and (3) the min of everything apart from the first element?
There are a variety of problems in this code including:
You don't use the result of the recursive findMin call.
startIndex will be the same for every call to findMin, because currentIndex is being set to the value of startIndex before startIndex is incremented.
If the number at index 1 in the array is <= the number at index 0, you just return that number without even making the recursive call.
A few observations in addition to the first answer:
int currentIndex = startIndex++; - you're going to miss your first element here. In general, you don't want to modify the input to your recursive function. Work off the input and generate new values when you're ready to call the function again - i.e. 'findMin(numbers, currentIndex+1, endIndex)'