Recursive function to difference between two values in array - java

I'm using Java.
I need to implement a recursive function that calculates the difference between each two values and returns for me array in size 2 [MAXIMUM_DIFF, STARTINDEX].
For the following array:
arr = {1, 4, 60, -10, 2, 7, 56, -10}
The recursive method returns array in size 2: [70,2] because the maximum difference is 70 (60-(-10)=70) and the index of 60 is 2.
I have 90% from the solution:
public static int[] getMax(int[] arr) {
int [] retArr = new int[2];
if(arr.length == 1)
return retArr;
else {
return getMax(arr, retArr);
}
}
public static int[] getMax(int[] arr, int[] retArr) {
if(retArr[1] == arr.length - 1)
return retArr;
int currentMaxVal = arr[retArr[1]] - arr[retArr[1] + 1];
if(currentMaxVal > retArr[0]) {
retArr[0] = currentMaxVal;
}
retArr[1] = retArr[1] + 1;
return getMax(arr, retArr);
}
But the result is[70,7] instead of [70,2] because this line retArr[1] = retArr[1] + 1;
This is because I don't know where to save the index, So how can I save the index?
*I'm not sure about the second param of getMax(int [] arr, int []retArr)
Its can be different maybe
I cant add another parameters, Maybe to change the second param of getMax(int [] arr, int []retArr), And I can't use static variables

if(currentMaxVal > retArr[0])
{
retArr[0] = currentMaxVal;
}
retArr[1] = retArr[1] + 1;
Should be
if(currentMaxVal > retArr[0])
{
retArr[0] = currentMaxVal;
retArr[1] = currentIndex;
}
And currentIndex should be an additional parameter passed to the function. (and other references to current index updated accordingly)
UPDATE:
I think the point here is to understand "divide and conquer", where you break up the problem into a smaller problem, and then sort through for the best one. Something like this (if a bit more awkward then a normal case)
public static int[] getMax(int[] arr, int[] retArr) {
// Return case
if (retArr[1] >= arr.length - 1)
return new int[] { Integer.MIN_VALUE, retArr[1] };
// Save context
int index = retArr[1];
int value = arr[index] - arr[index + 1];
// Call recursion
retArr[1]++;
int[] temp = getMax(arr, retArr);
// Return best between current case and recursive case
if (temp[0] > value)
return temp;
else
return new int[] { value, index };
}
Each call (or stack) of the recursive function is its own context. That means variables declared in it won't be overwritten in the recursive calls. The idea is that you break a hard problem down recursively until you can't break it down any further. Then you solve it by putting together the results of each call one at a time until you have your final answer. (This works better with less trivial cases like the fibonacci sequence) Also note that anything that can be done in a loop will always be more efficient then recursion.

Related

How I could find the maxim value of an array with recursive without having an index?

I have that method valorMaxim([1, 5, 252, 24, 7, 82, 3]) returns 252.
I don't know how to do it. I have been thinking if I could decrease the array length.
public static int valorMaxim(int arr[]){
int max;
if(arr.length==1)
return arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] < arr[i+1]) {
max=arr[i+1];
return arr[i+1];
}
}
return valorMaxim(arr);
//Retorna el valor màxim en un array no buit d’enters.
}
I modified the accepted answer to Finding Max value in an array using recursion.
As you suggested (i.e. decrease the array length with each recursive method invocation), I create a copy of the method parameter whose length is one less than the parameter and remove the first element. Then I recursively call the method with the array copy.
public class Main {
public static int valorMaxim(int arr[]){
if (arr.length == 1) {
return arr[0];
}
else {
int[] tmp = new int[arr.length - 1];
System.arraycopy(arr, 1, tmp, 0, tmp.length);
return Math.max(arr[0], valorMaxim(tmp));
}
}
public static void main(String[] args) {
System.out.println(valorMaxim(new int[]{1, 5, 252, 24, 7, 82, 3}));
}
}
Basically, the recursive idea is:
If the array has length 1, return the only element;
Otherwise, split the array into x the first element, and xs the rest;
Find the maximum element within xs, compare it to x and yield the greater.
There are two ways to achieve such a "split":
Create a new copy of part of the array for xs
You can either use System.arraycopy (see answer by #Abra) or Arrays.copyOfRange, which is simpler:
int x = arr[0];
int[] xs = Arrays.copyOfRange(arr, 1, arr.length);
And now we lookup the maximum element within xs (which is valorMaxim(xs)), and compare it to x as the final result:
return Math.max(x, valorMaxim(xs));
Put everything together, and don't forget to add a length checker:
public static int valorMaxim(int arr[])
{
if (arr.length == 1) return arr[0];
int x = arr[0];
int[] xs = Arrays.copyOfRange(arr, 1, arr.length);
return Math.max(x, valorMaxim(xs));
}
And that's it! Since we have the length checker in the first place,
we can safely make sure xs would never be empty, and hence valorMaxim(xs) would
never result in ArrayIndexOutOfBoundsException.
Set a boundary for the array
You may have found that copying a new array at each time could be time- and memory-consuming.
Instead of creating a physical copy for xs, we can conceptualise the idea
and use a bounded array instead. We would need to define a helper method to do so:
private static int findMaxBound(int arr[], int startFrom)
{
// does "xs" have length 1?
if (startFrom == arr.length - 1) return arr[startFrom];
int x = arr[startFrom];
int maxInXs = findMaxBound(arr, startFrom + 1);
return Math.max(x, maxInXs);
}
And then we can define valorMaxim as
public static int valorMaxim(int arr[])
{
return findMaxBound(arr, 0);
}
In the end, we did not create any new copies of arr
but uses different ranges of itself and treat them as xs throughout the process.

Write a recursive method called which takes in an array of integers and returns said array in reversed sorted order

I have a programming exam in a few days so I'm doing some exercises just to practice. However, I've been stuck with this problem and I started to doubt if it's possible to do it. Write a recursive method called arrayReverse which takes in an array of integers and returns said array in reversed sorted order. So an example would be:
input: [1,2,3]
output:[3,2,1]
I wasn't able to solve it. My intuition was to take the last element of the array, put it at the beginning, i,e: index[0] and then recursively call the rest of the array but then taking the new last element and put it on index[1]. Unfortunately, the implementation was harder than I thought but I (for the sake of trying) edited the question in a way that it accepts 2 arrays and this was my code:
import java.util.Arrays;
class Test {
int[] arrayReverse(int[] m, int[] mReverse) {
if (m.length == 1) {
mReverse[mReverse.length - 1] = m[0];
return mReverse;
} else {
int lastNum = m[m.length - 1];
mReverse[mReverse.length - m.length] = lastNum;
int[] arrayMinusOne = cropArray(m);
return arrayReverse(arrayMinusOne, mReverse);
}
}
int[] cropArray(int[] m) {
int[] mCropped = new int[m.length - 1];
for (int i = 0; i < m.length - 1; i++) {
mCropped[i] = m[i];
}
return mCropped;
}
}
void demo() {
int[] helpTest4 = new int[]{1, 2, 3};
int[] emptyArray = new int[helpTest4.length];
int[] test4 = arrayReverse(helpTest4, emptyArray);
System.out.println(Arrays.toString(test4));
}
public static void main(String[] args) {
new Test().demo();
}
}
It works perfectly but I'm not satisfied with the result because of two reasons:
I wasn't able to do it completely recursive. I used a for loop in cropArray.
I couldn't do it on one array.
How can this be done?
Option1: Using only one parameter (array) in the recursive function
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class MyClass {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] reversed = reverseArray(arr);
System.out.println(Arrays.toString(reversed));
}
public static int[] reverseArray(int[] arr)
{
if (arr.length == 0)
return arr;
// remove first element
int first = arr[0];
int[] list = Arrays.copyOfRange(arr, 1, arr.length);
//Calling Function Recursively get reversed array
int[] returnArr = reverseArray(list);
//Add original first to the last of the arrayToReturn
returnArr = Arrays.copyOf(returnArr, returnArr.length + 1);
returnArr[returnArr.length - 1] = first;
return returnArr;
}
}
Option2:
void reverseArray(int[] x){
reverse(x, 0, x.length -1);
}
void reverse(int[] x, int i, int j){
if(i<j){//Swap ith with jth element where i and j are equidistant from ends
int tmp = x[i];
x[i] = x[j];
x[j] = tmp;
reverse(x, ++i, --j);//Recursive
}
}
Test:
int[] s = new int[]{1,2,3,4,5};
reverseArray(s);
System.out.println(Arrays.toString(s));//"5,4,3,2,1"
Recursive, O(n), no temporary Array needed.
Please try the code below:
import java.util.*;
public class HelloWorld{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[]= new int[n];
for(int i=0;i<n;i++)
{
arr[i] = sc.nextInt();
}
Printsum(arr,0);
}
public static void Printsum(int arr[], int idx)
{
if(idx == arr.length)
return ;
Printsum(arr,idx+1);
System.out.println(arr[idx]);
}
}
I don't think this is a particularly good question - there is obviously a direct and clear way to do it without recursion; so the question does little to demonstrate any useful knowledge of recursion.
That said I believe the algorithm they were seeking uses the facts that:
a) reversing a 1 length array is trivial
b) you can reverse an n length array by appending the first element to the reverse the the last n-1 elements.
So code for this solution will look much simpler that what you currently have.
Ruby:
def reverse(a)
if a.empty?
return []
else
return [a.last] + reverse(a[0..-2])
end
end
a = [1, 2, 3]
reverse(a)
Taking the request literally, I have come out with a solution which only needs ONE recursive function with just ONE input/output parameter:
public static void arrayReverse(int[] input)
{
if (input.length > 0)
{
// Store locally the fist element:
int firstElement=input[0];
// Creates a sub-array and reverses it:
int[] input2=new int[input.length - 1];
System.arraycopy(input, 1, input2, 0, input2.length);
arrayReverse(input2);
// Copies back the reversed array into the current array:
System.arraycopy(input2, 0, input, 0, input2.length);
// Puts the stored fist element in the last position:
input[input.length - 1]=firstElement;
}
}
This solution is based upon a stack structure, for which it takes advantage of the machine calling stack at runtime, where the local values are stored while the function is executing.
The base case of this recursion is, of corse, the empty array.
In the generic case, the function stores locally the first element, then re-invokes itself recursively to reverse the rest of the array, and last, puts back the first element in the last position.

Java method to recursively add each integer in an array to all of the elements following it?

For example if I have an array of ints as a parameter to my method, my method needs to return an array of ints where each element is the sum of all the elements following it.
Example:
parameter is [5, 6, 7, 2, 3, 1] I need to return [24, 19, 13, 6, 4, 1]
I have a written a helper method that correctly adds an index to all of the ones after it here:
public static int sum(int[] array, int index) {
if (index == array.length) {
return array[array.length-1];
} else {
return array[index] + sum(array, index + 1);
}
}
This all works as it should, but I'm having trouble with the original method here:
public int[] reverseCumulative(int[] numbers) {
int[] temp = new int[numbers.length];
if (numbers.length == 0) {
return temp;
}
else {
temp[numbers.length-1] = sum(numbers, numbers.length);
numbers = Arrays.copyOf(numbers, numbers.length - 1);
reverseCumulative(numbers);
return temp;
}
}
The output here is [0, 0, 0, 0 , 0, 1]. I understand that this is most likely due to the fact I'm creating a new int[] temp every time I call the reverseCumulative method within itself, but I am completely lost and any push in the right direction would be appreciated.
Edit: Forgot to add, I am not allowed to use any loops.
Since you are creating a new array each time you call the reverseCumulative method, you should use the sum method as a helper method inside the reverseCumulative method so that you are still using recursion. For example,
public int[] reverseCumulative(int[] numbers) {
int[] temp = new int[numbers.length];
if (numbers.length == 0) {
return temp;
}
else {
for(int i = 0; i < numbers.length; i++){
temp[i] = sum(numbers,i);
}
return temp;
}
}
This way, each element in temp equals a sum of integers in the numbers array depending on which iteration it is currently on. In the first iteration, temp[0] = the sum of all the ints in numbers. In the second iteration, temp[1] = the sum of all the ints in numbers except the first int and so on. However, the way the sum method is written right now, it adds the last element twice so here's a simple fix,
public static int sum(int[] array, int index) {
if (index == array.length-1) {
return array[array.length-1];
} else {
return array[index] + sum(array, index + 1);
}
}
Maybe something like this?
public static int sum(final int[] target, final int[] source, int index) {
if (index >= source.length - 1)
return source[index];
return target[index] = source[index] + sum(target, source, index + 1);
}
public static int[] reverseCulmulative(final int[] array) {
final int[] target = array.clone();
sum(target, array, 0);
return target;
}

How can we swap two elements in an array?

The problem I am trying to solve is as follows:-
Given an array of ints length 3, return an array with the elements "rotated left" so {1, 2, 3} yields {2, 3, 1}
I came up with the following code:-
public int[] rotateLeft3(int[] nums) {
for(int i=0;i<2;i++)
swap(nums[i],nums[i+1]);
return nums;
}
public void swap(int a,int b)
{
int temp = a;
a = b;
b= temp;
}
However, it is not running successfully. In case of C++, I could have passed references as arguments and the problem would have been sorted then why is not happening here?
The following code is working:-
public int[] rotateLeft3(int[] nums) {
int temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
temp = nums[1];
nums[1] = nums[2];
nums[2] = temp;
return nums;
}
But this code is complete brute-force writing and I am not liking it very much. Can you please suggest how I can make the first approach work?
All parameters in java method calls are passed by value. You need to pass in the array and the two indexes you want to swap.
public void swap(int[] array, int a,int b)
{
int temp = array[a];
array[a] = array[b];
array[b]= temp;
}
As you have said the problem is passing by reference, C does it - Java doesn't. There are plenty of other ways to achieve the same ends though.
The simplest way is to pass the array and the two indexes to your swap function rather than the contents of the array at that index.
If you want a rotation that isn't limited by size, try:
public int[] rotateLeft(int[] nums){
if(nums.length == 0)
return new int[0];
int temp = nums[0];
//This loop starts at index 1 because we are moving
// elements left, and 0 can't move left.
for(int index = 1; index < nums.length; index++){
nums[index-1] = nums[index];
}
nums[nums.length-1] = temp;
}
you can also use the xor swap without the temp variable ;)
public void swap(int[] array, int ind1, int ind2) {
array[ind1] ^= array[ind2]
array[ind1] ^= (array[ind2] ^= array[ind1])
}
When you call the swap method , you are passing the values inside your array, but that method does not return the a and b values. Yes, that could be done in C/C++ with the use of pointers, but java does not have it.
Xynariz's code provide a way of doing the shift that is not limited to array size.
You can create a swap function with a single line usage pattern, but the calling format is not typical:
public int[] rotateLeft3(int[] nums) {
for(int i=0;i<2;i++)
nums[i+1] = swap(nums[i], nums[i]=nums[i+1]);
return nums;
}
// swaps any number of same type objects
public <T> T swap(T... args) {
// usage: z = swap(a, a=b, b=c, ... y=z);
return args[0];
}
This works because the first argument is passed into swap before the assignments happen in rest of the arguments.

Rewrite getLargest to recursive method in Java

I am doing this assignment and I am having trouble writing this method recursively.
I have this way to do it which is effective but not recursive:
public static <T extends Comparable< ? super T>> T getLargest(T [] a, int low,
int high)
{
if(low>high)
throw new IllegalArgumentException();
return Collections.max(Arrays.asList(Arrays.copyOfRange(a, low, high)));
So from there I went to this one, which kind of extends it but is not recursive either:
T[] arrCopy = (T[]) new Object[high-low];
for(int i=low;i<high;i++){
if(a[i].compareTo(a[i-1])>0)
arrCopy[i]=a[i];
else
arrCopy[i]=a[i+1];
}
return arrCopy[0];
And I've been working on it for hours and can't seem a way to make it recursive and make it work.
Any help and ideas are greatly appreciated!
Well, here is a template for turning a for-loop into a tail-recursive method:
//iterative version
public Object getIteratively(Object[] a) {
Object retVal = null;
for (int i = 0; i < a.length; a++ ) {
//do something
}
return retVal;
}
//recursive version
public Object getRecursively(Object[] a) {
doGetRecursively(a, 0, null);
}
private Object doGetRecursively(Object[] a, int i, Object retVal) {
if ( i == a.length ) {
return retVal;
}
//do something
return doGetRecursively(a, i+1, retVal);
}
Why you would ever want to do this in a non-functional language is beyond me though.
In this case //do something would be the same in both cases, e.g.:
if ( a[i].compareTo(retVal) > 0 ) {
retVal = a[i];
}
First, your method signature is incorrect. You do not need a 'low'. You should take an array/list as input and return the largest element. You may find however that you want a secondary method that requires extra arguments.
When approaching recursion and you're stuck, it's often best to identify your base case(s) first, then deal with your recursive case(s) next.
Your base case is the simplest case in which you know the answer. In this problem, you know what the largest element is right away if the size of your list is 1 - you just return the only element. You may want to think about the case where your list is empty as well.
Your recursive case then, is whenever your list has size greater than 1. In your recursive case, you want to try and 'break a piece off' and then send the rest to a recursive call. In this case, you can look at the first element in the list, and compare it to the result you get from a recursive call on the rest of the list.
This would be the right answer:
T tmp = a[low];
for(int i=0;i<=high;i++){
if(a[i].compareTo(tmp)>0){
tmp = a[i];
getLargest(a,i,high);
}
}
return tmp;
Okay before this gets out of hand, here's a simple iterative and the equivalent recursive solution to this - implemented with ints though so you have to change it a bit ;)
public static int getLargest(int[] vals) {
int max = vals[0];
for (int i = 1; i < vals.length; i++) {
max = Math.max(max, vals[i]);
}
return max;
}
public static int getLargestRec(int[] vals) {
return getLargestRec(vals, 0, vals.length);
}
private static int getLargestRec(int[] vals, int low, int high) {
if (low + 1 == high) {
return vals[low];
}
int middle = low + (high - low) / 2;
int left = getLargestRec(vals, low, middle);
int right = getLargestRec(vals, middle, high);
return Math.max(left, right);
}
public static void main(String[] args) {
int[] vals = {5, 23, 32, -5, 4, 6};
System.out.println(getLargestRec(vals));
System.out.println(getLargest(vals));
}
Note that as usual for recursive problems the lower bound is inclusive and the higher bound is exclusive. Also we could implement this differently as well, but the usual divide & conquer approach is rather useful and lends itself nicely to parallelization with a fork framework, so that's fine. (And yes for an empty array both versions will fail)

Categories