Java BinarySearchTree and recursion in variables - java

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?

Related

Finding product of odds in an array recursively

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.

Recursive function finding max value

I feel like I am pretty close, but my return value keeps printing out the first value in the array..
public static double mx(int[] nums, int track)
maxNow = nums[0];
if (count < [lengthofarray] - 1 && nums[track] != 0)
{
if (numbers[track] > maxval)
maxval = numbers[track];
System.out.println(maxval);
return maxval = mx(nums, track+1);
}
else
return maxval;
}
currentMax is a local variable declared inside findMax. This means that if findMax calls itself, which calls itself again, which calls itself again, so that it's now on the stack four times, there will be four different currentMax variables; each findMax has its own. Thus, if one of those findMax invocations modifies currentMax, it only modifies its own; the modification has no effect on the local currentMax variables belonging to the other invocations of findMax.
There are ways to get the method invocations to share the same currentMax (passing it as a parameter, as suggested in another answer, is a possibility), but you don't need them here. Instead, look at the problem a little differently: If you want to find the maximum of numbers[3] through numbers[10], you can call your function recursively to find the maximum of numbers[4] through numbers[10], then look at numbers[3] and compare it against the maximum you found recursively.
P.S. I do not recommend making currentMax a static field in order to get it to be shared; using a global field to hold results of recursion is usually poor programming practice, in my view. (It introduces thread-unsafety, for one thing.) There are ways to do this if done carefully, but in general I believe it should be avoided.
try to simplify the code:
public static int findMax(int[] numbers, int count){
if (count > 0) {
return Math.max(numbers[count], findMax(numbers, count-1))
}
else {
return numbers[0];
}
}
Here is how you can visualize this problem:
Your data can look like
{a, b, c, d, e}
you need to find max using
max(a, max(restOfElements))
which means you need to again use
max(a, max(b, max(restOfElements)))
.
.
.
max(a, max(b, max(c, max (d, max(e, nothing)))))
and last case can be visualized even better as
max(a, . . . . )
max(b, . . . )
max(c, . . )
max (d, . )
max(e, nothing)
So in the end you have two cases
when you are handling e, where you can't compare it with anything
when you are comparing current value with max of values after it
To handle first case you just need to return e because there is nothing else to compare it with.
To handle second case just get max value from rest of elements, compare it with your current value and return greater one.
Here is how your code can look like (hover over box to see code, but before you do it, try to implement it yourself again)
public static double findMax(double[] numbers, int count) {
if (count == numbers.length - 1)//we are handling last element
return numbers[count];
//else, we are returning greater number between current element,
//and max from rest of elements
return Math.max(numbers[count], findMax(numbers, count + 1));
}
Usage example:
double[] arr = { 1, 2, 2, 1, 4, 3 };
System.out.println(findMax(arr, 0));
Output: 4.0
As an exercise instead of dividing your problem inmax(a, max(b, max(c, max(d, max(e)))) try to create method which will do it like max(max(max(max(max(a), b), c), d), e)
Well since we're giving out answers, here's how I would do it:
max(arr[1-n]) = max(arr[1], max(arr[2-n]);
public static double findMax(final double ...arr){
return findMax(arr, 0);
}
private static double findMax(final double[] arr, final int start){
// base case, if this is the end of the array, the max of the "rest"
// is just this element
if(start == arr.length - 1)
return arr[start];
// else continue
// find the max of the rest of the array
final double nextMax = findMax(arr, start + 1);
// return this index if it's greater than the next max,
// else return the next max
return arr[start] > nextMax ? arr[start] : nextMax;
}
Here's my try at it:
public static double findMax(double[] numbers, int count, double currentMax){
if( count < numbers.length ){
if( numbers[count] > currentMax ){
currentMax = numbers[count];
}
currentMax = findMax( numbers, count+1, currentMax );
}
return currentMax;
}
What exactly is the purpose of && numbers[count] != 0? What if all your numbers are negative?
Second, try passing the currentmax as an argument, instead of initializing it inside the method. You want to keep track of your currentMax. Initializing it as a local variable would not do that, but would reset it to the first element at each call.
public static double findMax(double[] numbers, int count, double currentMax)
{
if (count < numbers.length)// && numbers[count] != 0) //While the value of count remains lower than the size of the array and the current element of the arraylist doesn't = 0, the execute the code..
{
if (numbers[count] > currentMax)
currentMax = numbers[count];
return currentMax = findMax(numbers, count+1, currentMax);
}
else return currentMax;
}

Arraylist basics

Write a method that recieves an ArrayList of integers as a parameter and returns the index of the largest integer in the collection.
So far I only have the code needed to receive an ArrayList of integers, search for a specific integer and return true.
Can anyone tell me what the int key is needed for? Wouldn't the code work without it?
public static boolean search (ArrayList<Integer>list, int key) {
for (int=0 ; i< listsize(); i++)
if (list.get(i) == key) {
return true;
} return false;
}
This should do the trick:
public int getIndexOfMaxValue(final List<Integer> list)
{
int maxFound = Integer.MIN_VALUE, value;
int ret = 0;
for (int index = 0; index < list.size(); index++) {
value = list.get(index);
if (value > maxFound) {
maxFound = value;
ret = index;
}
}
return ret;
}
Note that lists can have duplicate elements and that this code will return the index of the first maximum found. If you want the last index, just replace > with >= in the code above.
First you want to loop the ArrayList starting with i = 2 or 2nd element(assuming you have more than 1 element in the list),
if you have 1 or less than 1 element in then it simply skips the loop and returns 0 index(frst element). If the element of
if you have more than 1 element in the list, then it compares the value in the 2nd element to the value element before it, if it is higher or the same,then it sets it as the highestIntIdx.
public static int search(List list) {
int highestIntIdx= 0;
for (int i = 1;i<list.size();i++){
if(list.isEmpty())
break;
if (list.get(i) >= list.get(i-1)){
highestIntIdx = i;
}
}
return highestIntIdx;
}
}
The variable key is necessary because the method pictured appears to not be a method to find the max but rather a method to return whether the list contains a certain number.
The pictured method does have a logical error because the body of the loop returns immediately if the 0th index is not key:
if (list.get(i) == key) {
return true;
}
return false; // <- this should be after the loop
Regarding the method that's assigned (I assume it's an assignment):
Write a method that recieves an ArrayList of integers as a parameter and returns the index of the largest integer in the collection.
No, this method does not need a key variable.
To write a method such as this, the first thing you should do is make sure the list is not empty. An empty list cannot have a max index.
if(list.isEmpty()) {
return -1; // return a special value indicating the list is empty
}
That check will also throw a NullPointerException if the list is null. We could check if the list is null and return something else but this is a case where it's probably more informative to throw an exception.
Then you need to keep a variable that is the "current" highest index. We can initialize this to 0 because we already know the list is at least size of 1.
int indexOfMax = 0;
Then we'll have a loop that compares each index in the list to the current highest index and reassigns it if the number at that index is higher. We can start this loop at 1 because, again, we already know the list's size must at least be 1. The loop will simply break immediately if there are no other indexes. If a list only has one number, then that number is the largest one.
for(int i = 1; i < list.size(); i++) {
Then do the comparison and assignment:
if(list.get(i) > list.get(indexOfMax)) {
indexOfMax = i;
}
}
Finally return our index.
return indexOfMax;
You appear to have been asked to return the index of the largest integer in the ArrayList.
So you will want to implement a method liek
package com.snippet;
import java.util.ArrayList;
public class Largest {
public Largest() {
}
public int getIndexOfLargest(ArrayList<Integer> list) {
int index;
if (list == null) {
index = -1;
} else {
index = 0;
for (int i = 1; i < list.size(); i++) {
if (list.get(i) > list.get(index)) {
index = i;
}
}
}
return index;
}
}

find closest element in ArrayList

I have a sorted array. Given a key value (not necessarily in the table), I want to find the element in the table that is closes to the key value.
I have considered using a binary search, but I need to return the closest element if the key is not in the table (not -1). What should I try to do?
If there is no matches return -1. This is my current try with binary search:
public static long binarySearch (ArrayList<Long> arr, int first, int last, long key)
{
if (first > last) return -1;
int mid = first + (last - first)/2;
if (arr.get(mid) == key)
return mid;
else if (arr.get(mid) > key)
return binarySearch(arr, first, mid - 1, key);
else
return binarySearch(arr, mid + 1, last, key);
}
Change:
if (first > last) return -1;
to
if (first > last) {
// if either first or last is negative, return the first element.
// if either first or last are greater than arr length, return the last element.
// otherwise, get values in the array for indecies first and last, compare then to
// your key and return the closest.
}
Try something like (untested):
public static Long getClosest(List<Long> sortedList, Long key) {
int index = Collections.binarySearch(sortedList, key);
Long closest;
if (index >= 0) {
closest = sortedList.get(index);
} else {
index = -index - 1;
if (index == 0){
closest = sortedList.get(index);
} else if (index == sortedList.size()){
closest = sortedList.get(index - 1);
} else {
Long prev = sortedList.get(index - 1);
Long next = sortedList.get(index);
closest = ((key - prev) < (next - key)) ? prev : next;
}
}
return closest;
}
As said, this code is untested and you might have to check if it returns the correct value for all the corner cases.
When element at mid position isn't equal to key, You can calculate delta as abs(key-arr.get(mid)) and check whether it is lowest than actual delta (the lowest delta, the closest value You've got). In the end, if You don't find key in array, You return delta instead -1.
Notice, that You can NOT initialise delta with 0, because any later calculated delta will be greater than 0.
This will solve the question, to find the closest value, find the sum of the nearing index in the List, say for example {1,4,6,7,8,19} and key 3. the binary search will have the final subset with 1 and 4,
if (1+4 > 3+3) ? return 1 else return 4
if (first > last)
{
// This makes an Invalid case
return -1;
}
if (first == last)
{
// then get the valueOf(firstIndex)
return arr.get(first-1);
}
if (first + 1 == last)
{
// gets value from the first Index
int fistKey = arr.get(first-1);
// gets value from first Index + 1 i.e next Index
int nextKey = arr.get(first);
// if valueof(firstIndex) + valueOf(nextIndex) > key then,
// key will be closer to valueOf(firstIndex)
// else key will be closer to valueOf(nextIndex)
return ((fistKey + nextKey) > (key + key)) ? fistKey : nextKey;
}
else
{
// assuming List will start its index from 0, then "-1" used for mid calculation
int mid = (last+1)/2;
int keyFromList = arr.get(mid-1);
if (keyFromList == key)
return key;
if (keyFromList > key)
return binarySearch(arr, first, mid , key);
else
return binarySearch(arr, mid, last , key);
}
Fortunately, the Java standard libraries include Arrays.binarySearch which gives you the "insertion point" of an element if it is not included in an array:
Returns: index of the search key, if it is contained in the array;
otherwise, (-(insertion point) - 1). The insertion point is defined as
the point at which the key would be inserted into the array: the
index of the first element greater than the key, or a.length if all
elements in the array are less than the specified key. Note that
this guarantees that the return value will be >= 0 if and only if the
key is found.
With that we can implement your requirement very concisely:
import java.util.Arrays;
public class ClosestValue
{
static long closestValue(long[] sorted, long key)
{
if(sorted.length==1) {return sorted[0];} // trivial case
if(key<sorted[0]) {return sorted[0];} // lower boundary
if(key>sorted[sorted.length-1]) {return sorted[sorted.length-1];} // upper boundary
int pos = Arrays.binarySearch(sorted, key);
if(pos>=0) {return sorted[pos];} // we found an exact match
// we didn't find an exact match, now we have two candidates: insertion point and insertion point-1 (we excluded the trivial case before)
// pos = -ip-1 | +ip -pos => ip = -pos-1
int ip = -pos-1;
long closest;
if(sorted[ip]-key<key-sorted[ip-1]) {closest=sorted[ip];} // < can be <= if smaller value is preferred
else {closest=sorted[ip-1];}
return closest;
}
public static void main(String[] args)
{
System.out.println(closestValue(new long[] {1,4,6,7,8,19},3));
System.out.println(closestValue(new long[] {1,2,4,5},3));
System.out.println(closestValue(new long[] {1,2,4,5},7));
System.out.println(closestValue(new long[] {1,2,4,5},-5));
}
}

Recursive method to return number of zeroes

This is from an old test that I'm using to study.
I need to write a recursive method that returns the number of zeroes on the int[] from position 0 and right.
given int numberOfZeroes(int[] a, int right);
This assumes right < a.length
int numberOfZeroes(int[] a, int right) {
if(right < 0) { // We've gone through all indices
return 0; // So we don't want to recurse anymore
} else if(a[right] == 0) { // The current index has a zero
return 1 + numberOfZeroes(a, right - 1); // Call the function, moving left one. Add one to the returned count since we found a zero
} else { // The current index does not have a zero
return numberOfZeroes(a, right - 1); // Call the function, moving left one. We don't add anything since we didn't find a zero
}
}
int numberOfZeroes(int[] a, int right) {
if (right == 0) return 0;
return numberOfZeros(a, right-1) + a[right] == 0 ? 0 : 1;
}
Do numberOfZeros(a, a.length) to get the number of zeros in the entire array.

Categories