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

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.

Related

Double natural order not working as expected

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.

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) []

Sorting an array of int in lexicographic order

I came across a problem such that:
WAP to sort prime numbers smaller than given N by digits. If N is 40,
the output should be 11, 13, 17, 19, 2, 23, 29, 3, 31, 37, 39, 5, 7.
Note: Limit memory use.
Getting primary number was the easy. But I could not figure out an efficient way of lexicographic sorting of array of integer.
public static void getPrimeNumbers(int limit) {
for (int i=2; i<=limit; i++) {
if(isPrime(i)) {
System.out.println(i);
}
}
}
public static boolean isPrime(int number) {
for(int j=2; j<number; j++) {
if(number%j==0) {
return false;
}
}
return true;
}
public static void lexographicSorting() {
int[] input = {2,3,5,7,11,13,17,19};
int[] output = {};
for (int i=0; i<input.length; i++) {
for(int j=0; j<input.length; j++) {
////Stuck at this part.
}
}
}
Java String#compareTo already implements this functionality, you can access it pretty easily by converting your Integer objects to String objects and calling compareTo
Arrays.sort(input, new Comparator<Integer>() {
#Override
int compareTo( Integer x, Integer y ) {
return x.toString().compareTo( y.toString() );
}
};
I can say exactly how memory efficient this would be, you have to create 1 Integer object for each primitive int in your array, then you have to create 1 String object for each Integer object you have. So there is probably a good deal of overhead in object creation.
Given the constraints on the problem, the more efficient way to solve this problem is to not use String and Integer instances at all. One of the directives of the problem is to limit memory usage. In each of the answers so far, there has been a significant impact on memory (converting to and from Integer and String).
Here is a solution that is likely to be faster, and allocates no heap memory at all (although it has recursion so it may have some stack-effect - about the same as Arrays.sort()). This solves the problem from first-principles, it does not allocate a separate array for the results, and thus, it is relatively long compared to other solutions, but, those other solutions hide a mass of complexity that this solution does not have...
// this compare works by converting both values to be in the same 'power of 10',
// for example, comparing 5 and 20, it will convert 5 to 50, then compare 50 and 20
// numerically.
public static final int compareLexographicallyToLimit(final int limit, int a, int b) {
if (a == b) {
return 0;
}
if (a > limit || b > limit || a < 0 || b < 0) {
return a > b ? 1 : -1;
}
int max = Math.max(a, b);
int nextp10 = 1;
while (max > 10) {
max /= 10;
nextp10 *= 10;
}
while (a < nextp10) {
a *= 10;
}
while (b < nextp10) {
b *= 10;
}
return a > b ? 1 : -1;
}
private static void sortByRules(final int[] input, final int limit, final int from, final int to) {
if (from >= to) {
return;
}
int pivot = from;
int left = from + 1;
int right = to;
while (left <= right) {
while (left <= right && compareLexographicallyToLimit(limit, input[left], input[pivot]) <= 0) {
left++;
}
while (left <= right && compareLexographicallyToLimit(limit, input[pivot], input[right]) <= 0) {
right--;
}
if (left < right) {
int tmp = input[left];
input[left] = input[right];
input[right] = tmp;
left++;
right--;
}
}
int tmp = input[pivot];
input[pivot] = input[right];
input[right] = tmp;
sortByRules(input, limit, from, right-1);
sortByRules(input, limit, right+1, to);
}
public static void main(String[] args) {
int[] input = {2,3,5,7,11,13,17,19,31,37,41, 43, 100};
sortByRules(input, 40, 0, input.length - 1);
System.out.println(Arrays.toString(input));
sortByRules(input, 15, 0, input.length - 1);
System.out.println(Arrays.toString(input));
}
The only possible way is to implement your own Comparator where you will convert each of two comparable Integer-s to String objects and do comparison on them.
UPD: Here is an example, how to implement it:
Integer[] input = {2,3,5,7,11,13,17,19};
Arrays.sort(input, new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o1.toString().compareTo(o2.toString());
}
});
If you don't want to convert your integer values to strings (which can be wasteful), you can do something like this.
You can sort the numbers based on the most significant digits. See this post for computing the most significant digit of a number: Getting a values most significant digit in Objective C (it should be easy to port to Java).
Essentially you can use that function as part of your Comparator. You'll need a way to break ties (e.g., numbers with the same most significant digit(s)). If two numbers have the same most significant digits you can pluck them off and re-call this function over and over again as many times as necessary (until you can deem one number greater than the other, or until you run out of digits, indicating that they're equal).
Just to add to Hunter McMillen answer, Java 8's syntax allows defining a Comnparator in a much cleaner, leaner, way. Since Arrays.sort(int[]) does not have an overloaded variant that takes a Comparator, boxing the array is necessary in order to use a Comparator. E.g.:
int[] output =
Arrays.stream(input)
.boxed()
.sorted(Comparator.comparing(String::valueOf))
.mapToInt(Integer::intValue)
.toArray();

Heap Sort Questions

I am working on a homework problem that involves a heap sort implementation in java. Here is what I have so far
public class HeapSort {
public static void maxHeapify(int[] a, int i) {
int largest;
int l = 2*i;
int r = (2*i)+1;
if (l<=a.length-1 && a[l]>a[i]) {
largest = l;
}
else {
largest = i;
}
if (r<a.length-1 && a[r]>a[largest]) {
largest = r;
}
if (largest != i) {
int temp = a[i];
a[i] = a[largest];
a[largest] = temp;
maxHeapify(a,largest);
}
}
public static void buildMaxHeap(int[] a) {
for (int i=(a.length-1/2); i>=1; i--) {
maxHeapify(a,i);
}
}
public static void heapSort(int[] a) {
buildMaxHeap(a);
for (int i=a.length-1; i>=1; i--) {
int temp = a[0];
a[0] = a[i];
a[0] = temp;
maxHeapify(a,1);
}
}
Here is a main I put together to test (with output)
public static void main(String[] args) {
int[] tester = {3,2,9,45,7,15,21,11,36};
System.out.println(Arrays.toString(tester));
heapSort(tester);
System.out.println(Arrays.toString(tester));
}
[3, 2, 9, 45, 7, 15, 21, 11, 36]
[3, 45, 36, 21, 9, 15, 2, 11, 7]
I am not currently getting any errors but the output is just a bit off. Any help is very much appreciated. Thanks!
*Edited to add sample output
At a quick glance, I'd say you are missing a number of calls to maxHeapify(). It looks like you only maxHeapify() half of the heap (the half that ends in the rightmost branch), but not the rest. You must call maxHeapify() for all elements in a[0] to a[length/2].
You should move the recursive call to maxHeapify() out of the conditional for swapping. For the initial build of the heap, you must propagate all the way up to the root.
And you don't maxHeapify() the 'largest' element, but the one one level up the heap, so always i/2.
if (r<a.length-1 && a[r]>a[largest]) {
largest = r;
}
should be
if (r<=a.length-1 && a[r]>a[largest]) {
largest = r;
}
I believe you also have to call maxHeapify(a,0); instead of maxHeapify(a,1); in the last loop. Apart from that the -1/2 ordering issue in the comments mentioned above. That should do the job.

Finding the largest positive int in an array by recursion

I decided to implement a very simple program recursively, to see how well Java handles recursion*, and came up a bit short. This is what I ended up writing:
public class largestInIntArray {
public static void main(String[] args)
{
// These three lines just set up an array of ints:
int[] ints = new int[100];
java.util.Random r = new java.util.Random();
for(int i = 0; i < 100; i++) ints[i] = r.nextInt();
System.out.print("Normal:"+normal(ints,-1)+" Recursive:"+recursive(ints,-1));
}
private static int normal(int[] input, int largest) {
for(int i : input)
if(i > largest) largest = i;
return largest;
}
private static int recursive(int[] ints, int largest) {
if(ints.length == 1)
return ints[0] > largest ? ints[0] : largest;
int[] newints = new int[ints.length - 1];
System.arraycopy(ints, 1, newints, 0, ints.length - 1);
return recursive(newints, ints[0] > largest ? ints[0] : largest);
}
}
And that works fine, but as it's a bit ugly I wondered if there was a better way. If anyone has any thoughts/alternatives/syntactic sugar to share, that'd be much appreciated!
P.s. If you say "use Lisp" you win nothing (but respect). I want to know if this can be made to look nice in Java.
*and how well I handle recursion
Here's how I might make the recursive method look nicer:
private static int recursive(int[] ints, int largest, int start) {
if (start == ints.length) {
return largest;
}
return recursive(ints, Math.max(ints[start], largest), start + 1);
}
This avoids the expensive array copy, and works for an empty input array. You may implement an additional overloaded method with only two parameters for the same signature as the iterative function:
private static int recursive(int[] ints, int largest) {
return recursive(ints, largest, 0);
}
2 improvements:
no copy of the array (just using the offset)
no need to give the current max
private static int recursive(int[] ints, int offset) {
if (ints.length - 1 == offset) {
return ints[offset];
} else {
return Math.max(ints[offset], recursive(ints, offset + 1));
}
}
Start the recursion with recursive(ints, 0).
You could pass the current index as a parameter rather than copying almost the entire array each time or you could use a divide and conquer approach.
public static int max(int[] numbers) {
int size = numbers.length;
return max(numbers, size-1, numbers[size-1]);
}
public static int max(int[] numbers, int index, int largest) {
largest = Math.max(largest, numbers[index]);
return index > 0 ? max(numbers, index-1, largest) : largest;
}
... to see how well Java handles recursion
The simple answer is that Java doesn't handle recursion well. Specifically, Sun java compilers and Hotspot JVMs do not implement tail call recursion optimization, so recursion intensive algorithms can easily consume a lot of stack space.
However, I have seen articles that say that IBM's JVMs do support this optimization. And I saw an email from some non-Sun guy who said he was adding it as an experimental Hotspot extension as a thesis project.
Here's a slight variation showing how Linked Lists are often a little nicer for recursion, where "nicer" means "less parameters in method signature"
private static int recursive(LinkedList<Integer> list) {
if (list.size() == 1){
return list.removeFirst();
}
return Math.max(list.removeFirst(),recursive(list));
}
Your recursive code uses System.arrayCopy, but your iterative code doesn't do this, so your microbenchmark isn't going to be accurate. As others have mentioned, you can clean up that code by using Math.min and using an array index instead of the queue-like approach you had.
public class Maximum
{
/**
* Just adapted the iterative approach of finding maximum and formed a recursive function
*/
public static int max(int[] arr,int n,int m)
{
if(m < arr[n])
{
m = arr[n];
return max(arr,n - 1,m);
}
return m;
}
public static void main(String[] args)
{
int[] arr = {1,2,3,4,5,10,203,2,244,245,1000,55000,2223};
int max1 = max(arr,arr.length-1,arr[0]);
System.out.println("Max: "+ max1);
}
}
I actually have a pre made class that I setup for finding the largest integer of any set of values. You can put this class into your project and simply use it in any class like so:
System.out.println(figures.getLargest(8,6,12,9,120));
This would return the value "120" and place it in the output. Here is the methods source code if you are interested in using it:
public class figures {
public static int getLargest(int...f) {
int[] score = new int[f.length];
int largest=0;
for(int x=0;x<f.length;x++) {
for(int z=0;z<f.length;z++) {
if(f[x]>=f[z]) {
score[x]++;
}else if(f[x]<f[z]) {
}else {
continue;
}
if(z>=f.length) {
z=0;
break;
}
}
}
for(int fg=0;fg<f.length;fg++) {
if(score[fg]==f.length) {
largest = f[fg];
}
}
return largest;
}
}
The following is a sample code given by my Java instructor, Professor Penn Wu, in one of his lectures. Hope it helps.
import java.util.Random;
public class Recursion
{
static int s = 0;
public static Double max(Double[] d, int n, Double max)
{
if (n==0) { return max;}
else
{
if (d[n] > max)
{
max = d[n];
}
return max(d, n-1, max);
}
}
public static void main(String[] args)
{
Random rn = new Random();
Double[] d = new Double[15];
for (int i=0; i
{
d[i] = rn.nextDouble();
System.out.println(d[i]);
}
System.out.print("\nMax: " + max(d, d.length-1, d[0]));
}
}
Here is my alternative
public class recursion
{
public static int max( int[] n, int index )
{
if(index == n.length-1) // If it's simple, solve it immediately:
return n[index]; // when there's only one number, return it
if(max(n, index+1) > n [index]) // is one number bigger than n?
return max(n, index+1); // return the rest, which contains that bigger number
return n[index]; // if not, return n which must be the biggest number then
}
public static void main(String[] args)
{
int[] n = {100, 3, 5, 1, 2, 10, 2, 15, -1, 20, -1203}; // just some numbers for testing
System.out.println(max(n,0));
}
}

Categories

Resources