Java divide and conquer algorithm stack overflow error - java

I am trying to find out the index of the smallest number in an int array using divide and conquer and I have this stack overflow error:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.StrictMath.floor(Unknown Source)
at java.lang.Math.floor(Unknown Source)
This is my divide and conquer method:
private static int dC(int[] a, int f, int l) {
if(f == 1)
return f;
if(a[dC(a, f, (int)(Math.floor((double)(f+l)/2)))] > a[dC(a, (int)(Math.floor((double)(f+l)/2)+1), l)])
return dC(a, (int)(Math.floor((double)(f+l)/2)+1), l);
else
return dC(a, f, (int)(Math.floor((double)(f+l)/2)));
}
Here is what I put in my main method:
int[] a = {35,30,40,50};
System.out.println(dC(a, 0, 3));

You have a problem with your stoping "rule"
private static int dC(int[] a, int f, int l) {
if(l == f) // <-- This mean you have one item, so you want to return it.
return f;
if(a[dC(a, f, (int)(Math.floor((double)(f+l)/2)))] > a[dC(a, (int)(Math.floor((double)(f+l)/2)+1), l)])
return dC(a, (int)(Math.floor((double)(f+l)/2)+1), l);
else
return dC(a, f, (int)(Math.floor((double)(f+l)/2)));
}
Also, I would try to do the calculation only once, so something like this (also what Joop Eggen said about Integers arithmetics):
private static int dC(int[] a, int f, int l) {
if(l == f)
return f;
int m = (f+l) / 2;
int left = dC(a, f, m);
int right = dC(a, m+1, l);
if(a[left] > a[right])
return left;
else
return right;
}

This is just the classical binary search problem. From what I can glean by looking at your code, you seem to be getting bogged down in the logic used to make each recursive call to the left and right subarrays of the current array. The logic I used below is to take everything from the start to (start+end)/2 for the left recursion, and everything from ((start+end)/2) + 1 to end for the right recursion. This guarantees that there would never be any overlap.
The base case occurs when the algorithm finds itself sitting on a single entry in the array. In this case, we just return that value, and we do not recurse further.
private static int dC(int[] a, int start, int end) {
if (start == end) return a[start];
int left = dC(a, start, (start+end)/2);
int right = dC(a, ((start+end)/2) + 1, end);
return left < right ? left : right;
}
public static void main(String args[])
{
int[] a = {10, 3, 74, 0, 99, 9, 13};
System.out.println(dC(a, 0, 6)); // prints 0
}
Demo
Note: I have no idea what role Math.floor would be playing here, since you're using arrays of integer numbers, not doubles or floats. I removed this, because I saw no need for it.

It's a typical problem locating the index to the min/max, you can try it as:
public static void main(String... args) {
int[] arr = generateArrays(100, 1000, 0, 10000, true);
int minIndex = findMinIndex(arr, 1, arr.length - 1);
int theMin = arr[minIndex];
Arrays.sort(arr);
System.out.println(String.format("The min located correctly: %s", arr[0] == theMin));
}
private static int findMinIndex(int[] a, int l, int r) {
if (r - l < 1) return l;
int mid = l + (r - l) / 2;
int lIndex = findMinIndex(a, l + 1, mid);
int rIndex = findMinIndex(a, mid + 1, r);
int theMinIndex = l;
if (a[lIndex] < a[theMinIndex]) theMinIndex = lIndex;
if (a[rIndex] < a[theMinIndex]) theMinIndex = rIndex;
return theMinIndex;
}
And the helper to generate a random array.
public static int[] generateArrays(int minSize, int maxSize, int low, int high, boolean isUnique) {
Random random = new Random(System.currentTimeMillis());
int N = random.nextInt(maxSize - minSize + 1) + minSize;
if (isUnique) {
Set<Integer> intSet = new HashSet<>();
while (intSet.size() < N) {
intSet.add(random.nextInt(high - low) + low);
}
return intSet.stream().mapToInt(Integer::intValue).toArray();
} else {
int[] arr = new int[N];
for (int i = 0; i < N; ++i) {
arr[i] = random.nextInt(high - low) + low;
}
return arr;
}
}

Related

How can improve this algorithm to optimize the running time (find points in segments)

I'm given 2 integrals, the first is the number of segments (Xi,Xj) and the second is the number of points that can or cant be inside those segments.
As an example, the input could be:
2 3
0 5
8 10
1 6 11
Where, in first line, 2 means "2 segments" and 3 means "3 points".
The 2 segments are "0 to 5" and "8 to 10", and the points to look for are 1, 6, 11.
The output is
1 0 0
Where point 1 is in segment "0 to 5", and point 6 and 11 are not in any segment. If a point appears in more than one segment, like a 3, the output would be 2.
The original code, was just a double loop to search the points between segments. I used the Java Arrays quicksort (modified so when it sorts endpoints of segments, sorts also startpoints so start[i] and end[i] belong to the same segment i) to improve the speed of the double loop but it isnt enought.
The next code works fine but when there's too many segments it gets very slow:
public class PointsAndSegments {
private static int[] fastCountSegments(int[] starts, int[] ends, int[] points) {
sort(starts, ends);
int[] cnt2 = CountSegments(starts,ends,points);
return cnt2;
}
private static void dualPivotQuicksort(int[] a, int[] b, int left,int right, int div) {
int len = right - left;
if (len < 27) { // insertion sort for tiny array
for (int i = left + 1; i <= right; i++) {
for (int j = i; j > left && b[j] < b[j - 1]; j--) {
swap(a, b, j, j - 1);
}
}
return;
}
int third = len / div;
// "medians"
int m1 = left + third;
int m2 = right - third;
if (m1 <= left) {
m1 = left + 1;
}
if (m2 >= right) {
m2 = right - 1;
}
if (a[m1] < a[m2]) {
swap(a, b, m1, left);
swap(a, b, m2, right);
}
else {
swap(a, b, m1, right);
swap(a, b, m2, left);
}
// pivots
int pivot1 = b[left];
int pivot2 = b[right];
// pointers
int less = left + 1;
int great = right - 1;
// sorting
for (int k = less; k <= great; k++) {
if (b[k] < pivot1) {
swap(a, b, k, less++);
}
else if (b[k] > pivot2) {
while (k < great && b[great] > pivot2) {
great--;
}
swap(a, b, k, great--);
if (b[k] < pivot1) {
swap(a, b, k, less++);
}
}
}
// swaps
int dist = great - less;
if (dist < 13) {
div++;
}
swap(a, b, less - 1, left);
swap(a, b, great + 1, right);
// subarrays
dualPivotQuicksort(a, b, left, less - 2, div);
dualPivotQuicksort(a, b, great + 2, right, div);
// equal elements
if (dist > len - 13 && pivot1 != pivot2) {
for (int k = less; k <= great; k++) {
if (b[k] == pivot1) {
swap(a, b, k, less++);
}
else if (b[k] == pivot2) {
swap(a, b, k, great--);
if (b[k] == pivot1) {
swap(a, b, k, less++);
}
}
}
}
// subarray
if (pivot1 < pivot2) {
dualPivotQuicksort(a, b, less, great, div);
}
}
public static void sort(int[] a, int[] b) {
sort(a, b, 0, b.length);
}
public static void sort(int[] a, int[] b, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
dualPivotQuicksort(a, b, fromIndex, toIndex - 1, 3);
}
private static void rangeCheck(int length, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException("fromIndex > toIndex");
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
}
if (toIndex > length) {
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}
private static void swap(int[] a, int[] b, int i, int j) {
int swap1 = a[i];
int swap2 = b[i];
a[i] = a[j];
b[i] = b[j];
a[j] = swap1;
b[j] = swap2;
}
private static int[] naiveCountSegments(int[] starts, int[] ends, int[] points) {
int[] cnt = new int[points.length];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < starts.length; j++) {
if (starts[j] <= points[i] && points[i] <= ends[j]) {
cnt[i]++;
}
}
}
return cnt;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n, m;
n = scanner.nextInt();
m = scanner.nextInt();
int[] starts = new int[n];
int[] ends = new int[n];
int[] points = new int[m];
for (int i = 0; i < n; i++) {
starts[i] = scanner.nextInt();
ends[i] = scanner.nextInt();
}
for (int i = 0; i < m; i++) {
points[i] = scanner.nextInt();
}
//use fastCountSegments
int[] cnt = fastCountSegments(starts, ends, points);
for (int x : cnt) {
System.out.print(x + " ");
}
}
I believe the problem is in the CountSegments() method but I'm not sure of another way to solve it. Supposedly, I should use a divide and conquer algorithm, but after 4 days, I'm up to any solution.
I found a similar problem in CodeForces but the output is different and most solutions are in C++. Since I have just 3 months that I started to learn java, I think I have reached my knowledge limit.
Given the constrains by OP, let n be the # of segments, m be the number of points to be query, where n,m <= 5*10^4, I can come up with a O(nlg(n) + mlg(n)) solution (which should be enough to pass most online judge)
As each query is a verifying problem: Can the point be covered by some intervals, yes or no, we do not need to find which / how many intervals the point has been covered.
Outline of the algorithm:
Sort all intervals first by starting point, if tie then by length (rightmost ending point)
Try to merge the intervals to get some disjoint overlapping intervals. For e.g. (0,5), (2,9), (3,7), (3,5), (12,15) , you will get (0,9), (12,15). As the intervals are sorted, this can be done greedily in O(n)
Above are the precomputation, now for each point, we query using the disjoint intervals. Simply binary search if any interval contains such point, each query is O(lg(n)) and we got m points, so total O(m lg(n))
Combine whole algorithm, we will get an O(nlg(n) + mlg(n)) algorithm
This is an implementation similar to #Shole's idea:
public class SegmentsAlgorithm {
private PriorityQueue<int[]> remainSegments = new PriorityQueue<>((o0, o1) -> Integer.compare(o0[0], o1[0]));
private SegmentWeight[] arraySegments;
public void addSegment(int begin, int end) {
remainSegments.add(new int[]{begin, end});
}
public void prepareArrayCache() {
List<SegmentWeight> preCalculate = new ArrayList<>();
PriorityQueue<int[]> currentSegmentsByEnds = new PriorityQueue<>((o0, o1) -> Integer.compare(o0[1], o1[1]));
int begin = remainSegments.peek()[0];
while (!remainSegments.isEmpty() && remainSegments.peek()[0] == begin) {
currentSegmentsByEnds.add(remainSegments.poll());
}
preCalculate.add(new SegmentWeight(begin, currentSegmentsByEnds.size()));
int next;
while (!remainSegments.isEmpty()) {
if (currentSegmentsByEnds.isEmpty()) {
next = remainSegments.peek()[0];
} else {
next = Math.min(currentSegmentsByEnds.peek()[1], remainSegments.peek()[0]);
}
while (!currentSegmentsByEnds.isEmpty() && currentSegmentsByEnds.peek()[1] == next) {
currentSegmentsByEnds.poll();
}
while (!remainSegments.isEmpty() && remainSegments.peek()[0] == next) {
currentSegmentsByEnds.add(remainSegments.poll());
}
preCalculate.add(new SegmentWeight(next, currentSegmentsByEnds.size()));
}
while (!currentSegmentsByEnds.isEmpty()) {
next = currentSegmentsByEnds.peek()[1];
while (!currentSegmentsByEnds.isEmpty() && currentSegmentsByEnds.peek()[1] == next) {
currentSegmentsByEnds.poll();
}
preCalculate.add(new SegmentWeight(next, currentSegmentsByEnds.size()));
}
SegmentWeight[] arraySearch = new SegmentWeight[preCalculate.size()];
int i = 0;
for (SegmentWeight l : preCalculate) {
arraySearch[i++] = l;
}
this.arraySegments = arraySearch;
}
public int searchPoint(int p) {
int result = 0;
if (arraySegments != null && arraySegments.length > 0 && arraySegments[0].begin <= p) {
int index = Arrays.binarySearch(arraySegments, new SegmentWeight(p, 0), (o0, o1) -> Integer.compare(o0.begin, o1.begin));
if (index < 0){ // Bug fixed
index = - 2 - index;
}
if (index >= 0 && index < arraySegments.length) { // Protection added
result = arraySegments[index].weight;
}
}
return result;
}
public static void main(String[] args) {
SegmentsAlgorithm algorithm = new SegmentsAlgorithm();
int[][] segments = {{0, 5},{3, 10},{8, 9},{14, 20},{12, 28}};
for (int[] segment : segments) {
algorithm.addSegment(segment[0], segment[1]);
}
algorithm.prepareArrayCache();
int[] points = {-1, 2, 4, 6, 11, 28};
for (int point: points) {
System.out.println(point + ": " + algorithm.searchPoint(point));
}
}
public static class SegmentWeight {
int begin;
int weight;
public SegmentWeight(int begin, int weight) {
this.begin = begin;
this.weight = weight;
}
}
}
It prints:
-1: 0
2: 1
4: 2
6: 1
11: 2
28: 0
EDITED:
public static void main(String[] args) {
SegmentsAlgorithm algorithm = new SegmentsAlgorithm();
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
for (int i = 0; i < n; i++) {
algorithm.addSegment(scanner.nextInt(), scanner.nextInt());
}
algorithm.prepareArrayCache();
for (int i = 0; i < m; i++) {
System.out.print(algorithm.searchPoint(scanner.nextInt())+ " ");
}
System.out.println();
}

StackOverFlow error for QuickSort Algorithm

I am getting a StackOverflowError for this code. It says lines 184/185, which is where I initialize the split position (see below) and call the first recursive quickSort method. I can see that the code is having trouble exiting from the recursion, but I'm not sure where that is happening. Each time I call quickSort, it is on a smaller partition.
import java.util.*;
public class java2{
public static int MAXINT = 10000;
public static int[] intArray = new int[MAXINT];
public static int index;
public static long comparisons;
public static void main(String[] args)
{
System.out.println("SORTING ALGORITHM: Quicksort");
// Create a random array of integers and sort using the CombSort algorithm
// Print the number of items and comparisions
for(index = 10; index <= 10000; index = index * 10)
{
if (index == 10)
for(int i = 0; i < index; i++)
System.out.print(intArray[i] + " ");
comparisons = 0;
generate(intArray, index);
quickSort(intArray, 0, index - 1);
output(comparisons);
}
}
// Generate an array of random values between 0 and 10000
public static void generate(int[] valueArray, int count)
{
Random generator = new Random();
for(int temp = 0; temp < count; temp++)
{
valueArray[temp] = generator.nextInt(MAXINT) + 1;
}
}
// Print the number of values in the array and the number of comparisons
public static void output(long count)
{
System.out.println("Number of values in array: " + index);
System.out.println("Number of comparisons required: " + count);
System.out.println();
}
//Swap the given values and then assign them to the correct place in the array
public static void swap(int[] value, int i, int j)
{
int temp = value[i];
value[i] = value[j];
value[j] = temp;
}
//Implement Quicksort algorithm
public static void quickSort(int[] value, int startIndex, int endIndex)
{
int r = endIndex;
int l = startIndex;
int s;
if (l < r)
{
s = partition(intArray, l, r);
quickSort(intArray, l, s - 1); // StackOverflowError here
quickSort(intArray, s + 1, r);
}
}
//Partition an array into two parts
public static int partition(int[] value, int startIndex, int endIndex)
{
int r = endIndex;
int l = startIndex;
int p = value[l];
int i = l;
int j = r + 1;
while(i < j)
{
while(value[i] < p)
{
i++;
comparisons++;
}
while(value[j] > p)
{
j--;
comparisons++;
}
swap(value, i, j);
}
swap(value, i, j);
swap(value, l, j);
return j;
}
} // end main
Here are a few things to get you started with debugging.
You haven't posted your swap, but it's almost certainly incorrect. The way you're using it, its prototype would be void swap(int, int, int, int) which means it cannot have any effect on the value array. Try something like this:
public static void swap(int[] value, int i, int j) {
int temp = value[i];
value[i] = value[j];
value[j] = temp;
}
and use it like this:
swap(value, i, j);
Next, get the length=10 case correct. Print out the full array before and after sort, verify that the output is correct. When I run your code on an all zero array I get an infinite loop.
Next, if you're still having problems, add print statements!
By restructuring the partition method, the problem has been fixed:
public static int partition(int[] value, int p, int r)
{
int x = value[p];
int i = p - 1;
int j = r + 1 ;
while (true)
{
do
{
j--;
comparisons++;
}
while (value[j] > x);
do
{
i++;
comparisons++;
}
while (value[i] < x);
if (i < j)
{
swap(value, i, j);
}
else
return j;
}
}

Recursive max stack overflow error

I am trying to write a 3 input recursive program for max and min for a data structures class. I am getting a stack overflow error. I cannot tell if I am going off the end of the array, but I shouldn't be as far as my understanding goes. Any help would be appreciated. Here is my code:
class Extrema {
// maxArray()
// returns the largest value in int array A
// p is position zero, r is position length-1
static int maxArray(int[] A, int p, int r) {
int q;
if (p == r) {
return A[p];
} else {
q = (p + r)/2;
return max(maxArray(A, p, q-1), maxArray(A, q+1, r));
}
}
// max()
// returns the largest value of two ints
private static int max(int a, int b) {
return a > b ? a : b;
}
// main()
public static void main(String[] args) {
int[] B = {-1, 2, 6, 3, 9, 2, -3, -2, 11, 5, 7};
System.out.println( "max = " + maxArray(B, 0, B.length-1) ); // output: max = 11
}
}
Either do it non recursive since recursion really does not make any sense here:
static int maxArray(int[] A, int p, int r) {
int max = A[p];
for (int i = p + 1; i <= r; i++) {
if (A[i] > max)
max = A[i];
}
return max;
}
Or if you insist on some kind of recursion use your code existing with just a minor change:
return max(maxArray(A, p, q), maxArray(A, q+1, r));
Note the call to the first maxArray function now gets passed q and not q-1 as end index.
Change this code
if (p == r) {
return A[p];
}
to
if (p >= r) {
return A[p];
}
and note that when you call statement
return max(maxArray(A, p, q-1), maxArray(A, q+1, r));
you lose q element, so call
return max(maxArray(A, p, q), maxArray(A, q+1, r));

Finding Max value in an array using recursion

For one of the questions i was asked to solve, I found the max value of an array using a for loop, so i tried to find it using recursion and this is what I came up with:
public static int findMax(int[] a, int head, int last) {
int max = 0;
if (head == last) {
return a[head];
} else if (a[head] < a[last]) {
return findMax(a, head + 1, last);
} else {
return a[head];
}
}
So it works fine and gets the max value, but my question is : is it ok to have for the base case return a[head] and for the case when the value at the head is > the value at last?
You could just as easily do it with only one counter, just the index of the value you want to compare this time:
public static int findMax(int[] a, int index) {
if (index > 0) {
return Math.max(a[index], findMax(a, index-1))
} else {
return a[0];
}
}
This much better shows what is going on, and uses the default "recursion" layout, e.g. with a common base step. Initial call is by doing findMax(a, a.length-1).
It's actually much simpler than that. The base case is if you've reached the end of the array (the 'else' part of the ternary control block below). Otherwise you return the max of the current and the recursive call.
public static int findMax(int[] a) {
return findMax(a, 0);
}
private static int findMax(int[] a, int i) {
return i < a.length
? Math.max(a[i], findMax(a, i + 1))
: Integer.MIN_VALUE;
}
At each element, you return the larger of the current element, and all of the elements with a greater index. Integer.MIN_VALUE will be returned only on empty arrays. This runs in linear time.
I would solve this by dividing the array in to the half on each recursive call.
findMax(int[] data, int a, int b)
where a and b are array indices.
The stop condition is when b - a <= 1, then they are neighbours and the max is max(a,b);
The initial call:
findMax(int[] data, int 0, data.length -1);
This reduces the maximum recursion depth from N to log2(N).
But the search effort still stays O(N).
This would result in
int findMax(int[] data, int a, int b) {
if (b - a <= 1) {
return Math.max(data[a], data[b]);
} else {
int mid = (a+b) /2; // this can overflow for values near Integer.Max: can be solved by a + (b-a) / 2;
int leftMax = findMax(a, mid);
int rightMax = findMax(mid +1, b);
return Math.max(leftMax, rightMax);
}
}
I came across this thread and it helped me a lot. Attached is my complete code in both recursion and divide&conquer cases.
The run time for divide&conquer is slightly better than recursion.
//use divide and conquer.
public int findMaxDivideConquer(int[] arr){
return findMaxDivideConquerHelper(arr, 0, arr.length-1);
}
private int findMaxDivideConquerHelper(int[] arr, int start, int end){
//base case
if(end - start <= 1) return Math.max(arr[start], arr[end]);
//divide
int mid = start + ( end - start )/2;
int leftMax =findMaxDivideConquerHelper(arr, start, mid);
int rightMax =findMaxDivideConquerHelper(arr, mid+1, end);
//conquer
return Math.max( leftMax, rightMax );
}
// use recursion. return the max of the current and recursive call
public int findMaxRec(int[] arr){
return findMaxRec(arr, 0);
}
private int findMaxRec(int[] arr, int i){
if (i == arr.length) {
return Integer.MIN_VALUE;
}
return Math.max(arr[i], findMaxRec(arr, i+1));
}
What about this one ?
public static int maxElement(int[] a, int index, int max) {
int largest = max;
while (index < a.length-1) {
//If current is the first element then override largest
if (index == 0) {
largest = a[0];
}
if (largest < a[index+1]) {
largest = a[index+1];
System.out.println("New Largest : " + largest); //Just to track the change in largest value
}
maxElement(a,index+1,largest);
}
return largest;
}
I know its an old Thread, but maybe this helps!
public static int max(int[] a, int n) {
if(n < 0) {
return Integer.MIN_VALUE;
}
return Math.max(a[n-1], max(a, n - 2));
}
class Test
{
int high;
int arr[];
int n;
Test()
{
n=5;
arr = new int[n];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
high = arr[0];
}
public static void main(String[] args)
{
Test t = new Test();
t.findHigh(0);
t.printHigh();
}
public void printHigh()
{
System.out.println("highest = "+high);
}
public void findHigh(int i)
{
if(i > n-1)
{
return;
}
if(arr[i] > high)
{
high = arr[i];
}
findHigh(i+1);
return;
}
}
You can do it recursively as follows.
Recurrent relation it something like this.
f(a,n) = a[n] if n == size
= f(a,n+1) if n != size
Implementation is as follows.
private static int getMaxRecursive(int[] arr,int pos) {
if(pos == (arr.length-1)) {
return arr[pos];
} else {
return Math.max(arr[pos], getMaxRecursive(arr, pos+1));
}
}
and call will look like this
int maxElement = getMaxRecursive(arr,0);
its not okay!
your code will not find the maximum element in the array, it will only return the element that has a higher value than the elements next to it, to solve this problem,the maximum value element in the range can be passed as argument for the recursive method.
private static int findMax(int[] a, int head, int last,int max) {
if(last == head) {
return max;
}
else if (a[head] > a[last]) {
max = a[head];
return findMax(a, head, last - 1, max);
} else {
max = a[last];
return findMax(a, head + 1, last, max);
}
}
Optimized solution
public class Test1 {
public static int findMax(int[] a, int head, int last) {
int max = 0, max1 = 0;
if (head == last) {
return a[head];
} else if (a[head] < a[last]) {
max = findMax(a, head + 1, last);
} else
max = findMax(a, head, last - 1);
if (max >= max1) {
max1 = max;
}
return max1;
}
public static void main(String[] args) {
int arr[] = {1001, 0, 2, 1002, 2500, 3, 1000, 7, 5, 100};
int i = findMax(arr, 0, 9);
System.out.println(i);
}
}
Thanks #Robert Columbia for the suggestion!
Update: This following function is going to recursively start from index 0 and it will keep adding to this index value till it's equal to the Length of the array, if it's more we should stop and return 0. Once we're doing that, we need to get the max of every two items in the array so, for example:
A = [1 , 2 , 3 ];
A[0] ( 1 ) vs A[1] ( 2 ) = 2
A[1] ( 2 ) vs A[2] ( 3 ) = 3
Max(2,3) = 3 ( The answer )
public int GetMax(int [] A, int index) {
index += 1;
if (index >= A.Length) return 0;
return Math.Max(A[index], GetMax(A, index + 1));
}
static int maximumOFArray(int[] array,int n) {
int max=Integer.MIN_VALUE;
if(n==1) return array[0];
else
max=maximumOFArray(array, --n);
max= max>array[n] ? max : array[n];
return max;
}
private static int getMax(int [] arr, int idx) {
if (idx==arr.length-1 ) return arr[idx];
return Math.max(arr[idx], getMax (arr,idx+1 ));
}
public class FindMaxArrayNumber {
public static int findByIteration(int[] array) {
int max = array[0];
for (int j : array) {
max = Math.max(j, max);
}
return max;
}
public static int findByRecursion(int[] array, int index) {
return index > 0
? Math.max(array[index], findByRecursion(array, index - 1))
: array[0];
}
public static void main(String[] args) {
int[] array = new int[]{1, 2, 12, 3, 4, 5, 6};
int maxNumberByIteration = findByIteration(array);
int maxNumberByRecursion = findByRecursion(array, array.length - 1);
System.out.println("maxNumberByIteration: " + maxNumberByIteration);
System.out.println("maxNumberByRecursion: " + maxNumberByRecursion);
// Outputs:
// maxNumberByIteration: 12
// maxNumberByRecursion: 12
}
}
int maximum = getMaxValue ( arr[arr.length - 1 ], arr, arr.length - 1 );
public static int getMaxValue ( int max, int arr[], int index )
{
if ( index < 0 )
return max;
if ( max < arr[index] )
max = arr[index];
return getMaxValue ( max, arr, index - 1 );
}
I felt that using a tracker for current maximum value would be good.

HW Recursive Divide and Conquer Algorithm

I'm having a really big issue with finding the solution to my problem. I have to create a recursive, divide-and conquer algorithm that computes the length of the longest non-decreasing subsequence of elements in an array of integers. I have the following code, but it's not really working, any help would be much appreciated!!!
public class LongestSubSequence {
public static int getPartition(int[] a, int p, int r)
{
int mid = ((p+r)/2)-1;
int q=0;
int i = 1;
int j= mid+i;
int k = mid -i;
while (a[mid]<=a[j] && j < r)
{
q = j;
i++;
}
while (a[mid] >=a [k] && k > p)
{
q = k;
i++;
}
return q;
}
public static int getCount (int[]a, int p, int r)
{
int i = p;
int j = p+1;
int count = 0;
while (i<r && j<r)
{
if(a[i]<=a[j])
count++;
i++;
j++;
}
return count;
}
public static int getLongestSubsequence (int[] a, int p, int r) {
int count = 0;
if (p<r)
{
int q = getPartition (a, p, r);
count = getCount(a,p,r);
if (count < getLongestSubsequence(a,p,q))
count = getLongestSubsequence(a, p, q);
else if (count < getLongestSubsequence(a, q+1, p))
{
count = getLongestSubsequence(a, q+1, p);
}
}
return count;
}
public static int LongestSubsequence (int[] a) {
return getLongestSubsequence(a, 0, a.length);
}
public static void main(String[] args) {
int[] a = {1,3,5,9,2, 1, 3};
System.out.println(LongestSubsequence(a));
}
}
This is a pretty big body of code, and it's a little hard to follow with all the a's, r's, q's, etc.
In general, I would create an array (call it longestSeq) where longestSeq[i] is the length of the longest non-decreasing sequence found so far that starts at index, i, of your original sequence. For instance, if I had
int[] sequence = new int[] { 3, 5, 1, 2 }
then the algorithm would yield
longestSeq[0] = 2;
longestSeq[1] = 1;
longestSeq[2] = 2;
longestSeq[3] = 1;
So you would initialize longestSeq to all 0's, and then iterate through your list and fill in these values. At the end, just take the max of longestSeq.
Maybe start with just trying to make it work iteratively (without recursion) and then add recursion if that's a requirement.

Categories

Resources