Double natural order not working as expected - java

I'm trying to implement selection sort using generics. To do that I receive a comparator (Because I wanted to use the method Comparator#naturalOrder() while testing).
The problem is that when calling it with a Double array it does not work, but when calling it with an Integer array instead, it works.
Here is the selection sort implementation I made:
public static<V> void selectionSort(V[] arr, Comparator<V> cmp){
if (arr == null)
throw new IllegalArgumentException("Invalid array, can't be sorted");
int minIndex = -1;
for(int i = 0, j; i<arr.length; i++){
for (j = i; j<arr.length;j++){
if (minIndex == -1 || cmp.compare(arr[minIndex],arr[j])>0){
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}
private static<V> void swap(V[] arr, int i, int j) {
V aux = arr[i];
arr[i]=arr[j];
arr[j]=aux;
}
Here is the test that's failing:
#Test
public void selectionSortDoubleTest(){
arrDouble = new Double[]{5.5,2.5,1.2,8.0};
SelectionSort.selectionSort(arrDouble, Comparator.naturalOrder());
Assert.assertArrayEquals(new Double[]{1.2,2.5,5.5,8.0}, arrDouble);
}
And here is the test that works:
#Test
public void selectionSortIntegerTest(){
arr = new Integer[]{2,5,7,1};
SelectionSort.selectionSort(arr, Comparator.naturalOrder());
Assert.assertArrayEquals(new Integer[]{1, 2, 5, 7},arr);
}
The weird part is that in the first test the arrays differ at position [1], so both start with 1.2, but then arrDouble[1] is 8.0 which doesn't make any sense.
The assertion error message I receive:
Arrays first differed at element [1];
Expected :2.5
Actual :8.0

minIndex must be reset to -1 at each iteration of the outer loop. Otherwise you swap the previously found min element with the new one. Using a debugger makes it quite easy to spot such mistakes.

Related

Cannot read field "value" because "anotherByte" is null

Here I have a Quick Sort algorithm. The base class has the function isLessThan()
abstract public class Sort<T extends Comparable<T>> {
protected T[] array;
public boolean isLessThan(T obj1, T obj2) {
if (obj1.compareTo(obj2) < 0)
return true;
else
return false;
}
abstract public void sort(T[] array);
}
The actual algorithm picks a partition, splits the array into high, low and then recursively partitions the high and low arrays. However I cannot get past the part where I add elements to high and low:
public class Quick<T extends Comparable<T>> extends Sort<T> {
T[] low, high;
public void addLow(T element, int index) {
low[index] = element;
}
public void addHigh(T element, int index) {
high[index] = element;
}
public T[] partition(T[] arr, T partition) {
int lowCount = 0;
int highCount = 0;
low = (T[]) new Comparable[arr.length];
high = (T[]) new Comparable[arr.length];
// here I am adding each element to either high or low
for (int i = 0; i < arr.length; i++) {
if (arr[i] != null) {
if (isLessThan(arr[i], partition)) {
addLow(arr[i], i);
lowCount++;
} else {
addHigh(arr[i], i);
highCount++;
}
}
}
// the rest of this code probably isn't relevant to my problem
// sort low, then high
if (lowCount > 1) {
low = partition(low, low[0]);
}
if (highCount > 1) {
high = partition(high, high[0]);
}
// merge
T[] arr2 = (T[]) new Comparable[low.length + high.length];
int count = 0;
for(int i = 0; i < low.length; i++) {
arr2[i] = low[i];
count++;
}
for(int j = 0; j < high.length;j++) {
arr2[count++] = high[j];
}
return arr2;
}
public void sort(T[] arr)
{
T partition = arr[0];
arr = partition(arr, partition);
//set super to array
super.array = arr;
}
}
For some reason, I get this error when calling isLessThan():
Exception in thread "main" java.lang.NullPointerException: Cannot read field "value" because "anotherByte" is null
at java.base/java.lang.Byte.compareTo(Byte.java:490)
at java.base/java.lang.Byte.compareTo(Byte.java:56)
at Sort.isLessThan(Sort.java:6)
at Quick.partition(Quick.java:20)
at Quick.partition(Quick.java:33)
at Quick.sort(Quick.java:59)
at Main.main(Main.java:7)
What is causing this error?
My main looks like this:
public class Main {
public static void main(String[] args) {
Byte[] array = {121, 25, 44, 17, 30, 55, 29, 7, 81, 45, 79, 41, 108, 60, 83, 29, 77, 5, 17, 110};
Quick s = new Quick();
s.sort(array);
}
}
Your assumption the rest of this code probably isn't relevant to my problem is wrong. Because it is low[0] that is null indeed.
// the rest of this code probably isn't relevant to my problem
// sort low, then high
if (lowCount > 1) {
System.out.println("LOW: " + low[0]);
low = processPartition(low, low[0]);
}
if (highCount > 1) {
System.out.println("HIGH: " + high[0]);
high = processPartition(high, high[0]);
}
You instantiate both arrays and say they have the same dimension as the original array. This is okay.
low = (T[]) new Comparable[arr.length];
high = (T[]) new Comparable[arr.length];
But your mistake is, that you use the wrong indexing approach! You take the index from the for-loop and pass it as index to the arrays.
for (int i = 0; i < arr.length; i++) {
if (arr[i] != null) {
if (isLessThan(arr[i], partition)) {
addLow(arr[i], i);
lowCount++;
} else {
addHigh(arr[i], i);
highCount++;
}
}
But what happens?
With the very first comparison you have 121 on 121. This is not less than but equal. In case of higher or equal you go into the else-part and call addHigh().
So index 0 is gone for a High.
Now the comparison goes on and on and all the others are LessThan() because 121 is the highest number in your list.
But, as you hand in the index from the loop, the first LessThan()-value does not go into low[0] but low[1]. low[0] is null!
And then you later call low = processPartition(low, low[0]); and get your NPE.
So you have at least 1 thing to do:
DON'T USE the index i out of your for-loop! That's wrong!
DO USE your counter lowCount and highCount instead! They will always point to the correct field in the array!
Please note, that this will only explain why you get the first NPE here and help you to solve it.
When you run this code the same NPE-message will occur, but at another point in the process. This time, because you alway pass the arrays around and constantly change them. When the code somewhen comes back to the very first round and proceeds, it will find highCount > 1 and tries to process the high[]-array. But this has changed in the meantime and high[0] is null.
You have to rethink you entire sorting approach here.
I hope this helps at least to figure out what went wrong in the first place.

Combination Sum Debugging

I have written some code to try to solve this challenge, but its not working, i can't seem to figure out where it went wrong, i can find the answer online but that's not the point i'm trying to see why my code doesn't work.
question:
Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
The same repeated number may be chosen from candidates unlimited number of times.
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
this is what i have came up with:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
helper(res,new ArrayList<Integer>(), candidates,target,0,0);
return res;
}
//current = current sum, we want it to be target
//start is index we are at and where the for loop starts
public void helper(List<List<Integer>> res, List<Integer> temp, int[] nums, int target, int current, int start){
if(start>=nums.length){
return;
}
if(current>=target){
if(current==target){
res.add(new ArrayList<>(temp));
}
temp.remove(temp.size()-1);
helper(res,temp,nums,target,current-nums[start],start+1);
return;
}
for(int i=start; i<nums.length; i++){
temp.add(nums[i]);
helper(res,temp,nums,target,current+nums[i],start);
}
}
}
explanation of my code:
so i am trying to use recursion backtracking here. i keep for looping an element in the array till the sum is >= target.if its >target i remove the last element since that made it bigger than target and try the other ones. if its = target i add it to result and i remove last element to try find more combinations.
but apparently i am getting error in this line:
temp.remove(temp.size()-1); //saying index out of bounds i am trying to remove when arraylist is empty
so it isnt running how i thought, because if the list is empty current should be 0 and it should even enter that if loop and should never be removed but it is and i am not sure why.
thanks.
The main issue if from trying to roll back the current variable value and call the helper method again from there in the if(current>=target) if statement. You can use the for loop to automatically do that for you and remove the added number after it returns. Then using the functions return to update the start value so that it will continue from where you left off will eliminate duplicates.
And because of the for loop num[i] will never go out of bounds so you dont have to worry about
if(start>=nums.length){
return;
}
This is the working version using your solution method
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
helper(res,new ArrayList<Integer>(), candidates,target,0,0);
return res;
}
public static int helper(List<List<Integer>> res, List<Integer> temp, int[] nums, int target, int current, int start){
if(current>=target){
if(current==target){
res.add(new ArrayList<>(temp));
}
return start + 1;
}
for(int i=start; i<nums.length; i++){
temp.add(nums[i]);
start = helper(res,temp,nums,target,current+nums[i],start);
temp.remove(temp.size()-1);
}
return start;
}
Running the code:
public static void main(String []args){
List<List<Integer>> res = combinationSum(new int[] {2,3,6,7}, 7);
System.out.println(res);
}
Result:
[[2, 2, 3], [7]]
Try this.
static List<List<Integer>> combinationSum(int[] candidates, int target) {
int size = candidates.length;
List<List<Integer>> result = new ArrayList<>();
new Object() {
void search(int index, int sum, List<Integer> selected) {
if (index >= size) {
if (sum == target)
result.add(new ArrayList<>(selected));
} else {
int candidate = candidates[index];
List<Integer> nextSelected = new ArrayList<>(selected);
for (int nextSum = sum; nextSum <= target; nextSum += candidate, nextSelected.add(candidate))
search(index + 1, nextSum, nextSelected);
}
}
}.search(0, 0, new ArrayList<>());
return result;
}
and
int[] candidates = {2, 3, 6, 7};
int target = 7;
List<List<Integer>> result = combinationSum(candidates, target);
System.out.println(result);
result:
[[7], [2, 2, 3]]

Can't change variable while doing recursion

public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[5];
rekursiq(a, b, 0, 0, 1);
}
static void rekursiq(int[] a, int[] b, int index, int start, int check) {
if (index == b.length){
System.out.println(java.util.Arrays.toString(b));
} else {
for (int i = start; i < a.length; i++) {
b[index] = a[i];
rekursiq(a, b, index + 1, i + 1, check + 1);
}
}
}
Now my question is: Instead of b.length in the recursion bottom I want to place an int check, and make check go +1 on every going there, and do something.
while (check < b.length) go the if statement, else return; but I can't seem to 1) increase the value properly and 2) make this while correctly. I don't know why.
I think my best try was
static void rekursiq(int[] a, int[] b, int index, int start, int check) {
if (check > b.length) {
return;
} else {
if (index == check) {
System.out.println(java.util.Arrays.toString(b));
} else {
for (int i = start; i < a.length; i++) {
b[index] = a[i];
rekursiq(a, b, index + 1, i + 1, check + 1);
}
}
}
}
But it did not work, and I hope some one of you can tell me why and how to fix it.
The value of check does increase when the method is called recursively. However, the problem you have is independent of check.
The Problem
Let me start by repeating what abhishrp already briefly mentioned: In this particular case, you want to either use a loop to iterate over all elements in the array, or recursion, but not use a loop inside of your recursive method. The reason is the following: At each step in the recursion, you look at exactly one element: the element at position index.
The Solution
So, how would you recursively copy an array? Let us assume you have a source array (in your code a) and an empty destination array (in your code b). Now, we know how to copy a single element of the array, namely destination[index] = source[index], and we can imagine copying the array as copying the first element, and then copying the subarray starting at the second element. Note that knowing how to copy a single element in an array implies knowing how to copy an array containing only one element.
This leads us to the following recursion, which we will turn to code shortly after:
if the given index dereferences the last element in the array, then copy this last element.
otherwise, copy the element at the current index, and copy the subarray starting at the next index.
Or expressed in Java:
static void copyValuesFromSourceToDestinationStartingAtIndex(int[] source, int[] destination, int index) {
if (isIndexOfLastElementInArray(index, destination)) {
destination[index] = source[index];
} else {
destination[index] = source[index];
copyValuesFromSourceToDestinationStartingAtIndex(source, destination, index + 1);
}
}
static boolean isIndexOfLastElementInArray(int index, int[] array){
return index == array.length - 1;
}
Note that you have too many parameters in your code: The parameter check is really just index, as you want to check whether the index is still inside the bounds of the array. I don't really know what you intended to do with the variable start though - seems like somehow you got confused there because of the loop.
Sidenote
Also, a small justification on why the true-branch of the if-statement in the above code does copy the last element instead of returning nothing if the index is out of bounds as in your code. It's perfectly reasonable to do it like you did. The argument "We trivially know how to copy an empty array" just didn't seem as natural as "knowing how to copy a single element implies knowing how to copy an array consisting of a single element". I encourage you however to adjust the code to "copy an empty array" as a base-case, because it removes the duplication, and more importantly, allows you to copy empty arrays (for which the above implementation would fail horribly).
Code
I also tried to give a comparison between the iterative and the recursive approach:
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
int[] copyOfAUsingIteration = copyArrayUsingIteration(a);
int[] copyOfAUsingRecursion = copyArrayUsingRecursion(a);
assert(Arrays.equals(copyOfAUsingIteration, copyOfAUsingRecursion));
assert(copyOfAUsingIteration != a);
assert(copyOfAUsingRecursion != a);
System.out.println(java.util.Arrays.toString(copyOfAUsingIteration));
System.out.println(java.util.Arrays.toString(copyOfAUsingRecursion));
}
static int[] copyArrayUsingIteration(int[] arrayToCopy) {
int[] result = new int[arrayToCopy.length];
for(int index = 0; index < result.length; index++){
result[index] = arrayToCopy[index];
}
return result;
}
static int[] copyArrayUsingRecursion(int[] arrayToCopy){
if (arrayToCopy.length == 0){
return new int[0];
} else {
int[] result = new int[arrayToCopy.length];
copyValuesFromSourceToDestinationStartingAtIndex(arrayToCopy, result, 0);
return result;
}
}
static void copyValuesFromSourceToDestinationStartingAtIndex(int[] source, int[] destination, int index) {
if (isIndexOfLastElementInArray(index, destination)) {
destination[index] = source[index];
} else {
destination[index] = source[index];
copyValuesFromSourceToDestinationStartingAtIndex(source, destination, index + 1);
}
}
static boolean isIndexOfLastElementInArray(int index, int[] array){
return index == array.length - 1;
}
To copy one array to another you can use either iteration or recursion. There is no need to do both. By this I mean there is no need for the for loop inside the rekursiq method.

algorithm removing duplicate elements in array without auxillay storage

I am working on this famous interview question on removing duplicate elements in array without using auxillary storage and preserving the order;
I have read a bunch of posts; Algorithm: efficient way to remove duplicate integers from an array, Removing Duplicates from an Array using C.
They are either implemented in C (without explanation) or the Java Code provided just fails when there is consecutive duplicates such as [1,1,1,3,3].
I am not quite confident with using C, my background is Java. So I implemented the code myself;
it follows like this:
use two loops, the outer-loop traverses the array and inner loop checks for duplicates and if present replace it with null.
Then I go over the duplicate-replaced-null array and remove null elements and replacing it with the next non-null element.
The total run-time I see now is O(n^2)+O(n) ~ O(n^2). Reading the above posts, I understood this is the best we can do, if no sorting and auxiliary storage is allowed.
My code is here: I am looking for ways to optimize any further (if there is a possibility) or a better/simplisitc logic;
public class RemoveDup {
public static void main (String[] args){
Integer[] arr2={3,45,1,2,3,3,3,3,2,1,45,2,10};
Integer[] res= removeDup(arr2);
System.out.println(Arrays.toString(res));
}
private static Integer[] removeDup(Integer[] data) {
int size = data.length;
int count = 1;
for (int i = 0; i < size; i++) {
Integer temp = data[i];
for (int j = i + 1; j < size && temp != null; j++) {
if (data[j] == temp) {
data[j] = null;
}
}
}
for (int i = 1; i < size; i++) {
Integer current = data[i];
if (data[i] != null) {
data[count++] = current;
}
}
return Arrays.copyOf(data, count);
}
}
EDIT 1; Reformatted code from #keshlam throws ArrayIndexOutofBound Exception:
private static int removeDupes(int[] array) {
System.out.println("method called");
if(array.length < 2)
return array.length;
int outsize=1; // first is always kept
for (int consider = 1; consider < array.length; ++consider) {
for(int compare=0;compare<outsize;++compare) {
if(array[consider]!=array[compare])
array[outsize++]=array[consider]; // already present; advance to next compare
else break;
// if we get here, we know it's new so append it to output
//array[outsize++]=array[consider]; // could test first, not worth it.
}
}
System.out.println(Arrays.toString(array));
// length is last written position plus 1
return outsize;
}
OK, here's my answer, which should be O(N*N) worst case. (With smaller constant, since even worstcase I'm testing N against -- on average -- 1/2 N, but this is computer science rather than software engineering and a mere 2X speedup isn't significant. Thanks to #Alexandru for pointing that out.)
1) Split cursor (input and output advanced separately),
2) Each new value only has to be compared to what's already been kept, and compare can stop if a match is found. (The hint keyword was "incremental")
3) First element need not be tested.
4) I'm taking advantage of labelled continue where I could have instead set a flag before breaking and then tested the flag. Comes out to the same thing; this is a bit more elegant.
4.5) I could have tested whether outsize==consider and not copied if that was true. But testing for it would take about as many cycles as doing the possibly-unnecessary copy, and the majority case is that they will not be the same, so it's easier to just let a possibly redundant copy take place.
5) I'm not recopying the data in the key function; I've factored out the copy-for-printing operation to a separate function to make clear that removeDupes does run entirely in the target array plus a few automatic variables on the stack. And I'm not spending time zeroing out the leftover elements at the end of the array; that may be wasted work (as in this case). Though I don't think it would actually change the formal complexity.
import java.util.Arrays;
public class RemoveDupes {
private static int removeDupes(final int[] array) {
if(array.length < 2)
return array.length;
int outsize=1; // first is always kept
outerloop: for (int consider = 1; consider < array.length; ++consider) {
for(int compare=0;compare<outsize;++compare)
if(array[consider]==array[compare])
continue outerloop; // already present; advance to next compare
// if we get here, we know it's new so append it to output
array[outsize++]=array[consider]; // could test first, not worth it.
}
return outsize; // length is last written position plus 1
}
private static void printRemoveDupes(int[] array) {
int newlength=removeDupes(array);
System.out.println(Arrays.toString(Arrays.copyOfRange(array, 0, newlength)));
}
public static void main(final String[] args) {
printRemoveDupes(new int[] { 3, 45, 1, 2, 3, 3, 3, 3, 2, 1, 45, 2, 10 });
printRemoveDupes(new int[] { 2, 2, 3, 3 });
printRemoveDupes(new int[] { 1, 1, 1, 1, 1, 1, 1, 1 });
}
}
LATE ADDITION: Since folks expressed confusion about point 4 in my explanation, here's the loop rewritten without labelled continue:
for (int consider = 1; consider < array.length; ++consider) {
boolean matchfound=false;
for(int compare=0;compare<outsize;++compare) {
if(array[consider]==array[compare]) {
matchfound=true;
break;
}
if(!matchFound) // only add it to the output if not found
array[outsize++]=array[consider];
}
Hope that helps. Labelled continue is a rarely-used feature of Java, so it isn't too surprising that some folks haven't seen it before. It's useful, but it does make code harder to read; I probably wouldn't use it in anything much more complicated than this simple algorithm.
Here one version which doesn't use additional memory (except for the array it returns) and doesn't sort either.
I believe this is slightly worse than O(n*log n).
Edit: I'm wrong. This is slightly better than O(n^3).
public class Dupes {
private static int[] removeDupes(final int[] array) {
int end = array.length - 1;
for (int i = 0; i <= end; i++) {
for (int j = i + 1; j <= end; j++) {
if (array[i] == array[j]) {
for (int k = j; k < end; k++) {
array[k] = array[k + 1];
}
end--;
j--;
}
}
}
return Arrays.copyOf(array, end + 1);
}
public static void main(final String[] args) {
System.out.println(Arrays.toString(removeDupes(new int[] { 3, 45, 1, 2, 3, 3, 3, 3, 2, 1, 45, 2, 10 })));
System.out.println(Arrays.toString(removeDupes(new int[] { 2, 2, 3, 3 })));
System.out.println(Arrays.toString(removeDupes(new int[] { 1, 1, 1, 1, 1, 1, 1, 1 })));
}
}
and here's a modified version which doesn't shift all of the elements from after the dupe. Instead it simply switches the dupe with the last, non-matching element. This obviously can't guarantee order.
private static int[] removeDupes(final int[] array) {
int end = array.length - 1;
for (int i = 0; i <= end; i++) {
for (int j = i + 1; j <= end; j++) {
if (array[i] == array[j]) {
while (end >= j && array[j] == array[end]) {
end--;
}
if (end > j) {
array[j] = array[end];
end--;
}
}
}
}
return Arrays.copyOf(array, end + 1);
}
Here you have a worst case of O(n^2) where the return points to the first non unique element. So everything before it is unique.
Instead of C++ iterators indices in Java can be used.
std::vecotr<int>::iterator unique(std::vector<int>& aVector){
auto end = aVector.end();
auto start = aVector.begin();
while(start != end){
auto num = *start; // the element to check against
auto temp = ++start; // start get incremented here
while (temp != end){
if (*temp == num){
std::swap(temp,end);
end--;
}
else
temp++; // the temp is in else so that if the swap occurs the algo should still check the swapped element.
}
}
return end;
}
Java equivalent code: (the return will be an int which is the index of the first not unique element)
int unique(int[] anArray){
int end = anArray.length-1;
int start = 0;
while(start != end){
int num = anArry[start]; // the element to check against
int temp = ++start; // start get incremented here
while (temp != end){
if (anArry[temp] == num){
swap(temp,end); // swaps the values at index of temp and end
end--;
}
else
temp++; // the temp is in else so that if the swap occurs the algo should still check the swapped element.
}
}
return end;
}
The slight difference in this algo and yours is in your point 2. Where instead of replacing the current element with null you go with swapping it with the last possibly unique element which on the first swap is the last element of array, on second swap the second last and so on.
You might as well consider looking at the std::unique implementation in C++ which is linear in one less than the distance between first and last: Compares each pair of elements, and possibly performs assignments on some of them., but as it was noted by #keshlam it is used on sorted arrays only. The return value is the same as in my algo. Here is the code directly from the standard library:
template<class _FwdIt, class _Pr> inline
_FwdIt _Unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
{ // remove each satisfying _Pred with previous
if (_First != _Last)
for (_FwdIt _Firstb; (_Firstb = _First), ++_First != _Last; )
if (_Pred(*_Firstb, *_First))
{ // copy down
for (; ++_First != _Last; )
if (!_Pred(*_Firstb, *_First))
*++_Firstb = _Move(*_First);
return (++_Firstb);
}
return (_Last);
}
To bring in a bit perspective - one solution in Haskell, it uses lists instead of arrays
and returns the reversed order, which can be fixed by applying reverse at the end.
import Data.List (foldl')
removeDup :: (Eq a) => [a] -> [a]
removeDup = foldl' (\acc x-> if x `elem` acc then acc else x:acc) []

Change elements of array to a[i] = i recursively

public static void what(int[] arr, int i)
{
if (i == 0)
return;
arr[arr.length - i] = i;
i--;
what(arr, i); // recursive method call
}
What I have here doesn't change anything, the array stays the same and a[i] doesn't = i. My logic is way off, any help?
I did a previous code where I had to set elements in an int array to zero, clearing the array. I used that as a basis for this initialization as well.
If you want a[i] = i then change to this:
public static void what(int[] arr, int i)
{
if (i == 0)
return;
arr[arr.length - i] = arr.length - i;
i--;
what(arr, i); // recursive method call
}
is this what you need ?
public static void what (int[] arr, int i)
{
if (i == 0)
return;
arr[i-1] = i-1;
i--;
what(arr, i); // recursive method call
}
This method will always return an array of the following content.
int arr[] = {0, 1, 2, 3, ..., n-1};
Your input array may be something like this. That may be the reason of your results not changing.
Recursion is pointless in this case because you will need more code, including a cycle, to validate the second parameter rather to solve the task.
The best case scenario for int[] intArr = new int[]{43,56,24,745,32} is to call what(intArr, 5) and get int[]{5,4,3,2,1}
Ofcourse, we have the most obvious issue: what(intArr,4343) will lead us to java.lang.ArrayIndexOutOfBoundsException but it can be fixed with ease: if( i <= arr.length && i>0 ).
It will be much more interesting if we will pass random value between 0 and 5(intArr.length)
what(intArr,2) will result in int[]{43, 56, 24, 2, 1}. How will you handle this case? The only way I see is to loop through intArr from i+1 to intArr.length-1 and check if we already performed what(intArr,3), what(intArr,4) and what(intArr,5).
Each time you call your method, you will need to loop through i-1 elements and check if it was processed already.
I would prefer to use a regular function with a loop:
public static void what(int[] arr)
{
for(int i = 0; i<arr.length; i++){
arr[i] = arr.length-i;
}
}
I feel like it is more readable, easier to understand if you do it the other way, starting from the front.
private static void what( int[] arr, int i )
{
if( i >= arr.length )
return;
arr[i] = i;
what( arr, i + 1 );
}
Here is it running.
I would try calling the function like what(array,array.length):
public static void what(int[] arr, int i)
{
if ( i == 0 )
return;
arr[i] = i;
what(arr, i-1); // recursive method call
}

Categories

Resources