This is my current code for a program to find the maximum subarray. I am getting the out of bounds error for 3 lines: I'm getting the error ArrayIndexOutOfBoundsException: index -25 out of bonds for length 16. I'm testing it with the array int[]{13,-3,-25,-20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}. I've only seen this error when using the wrong numbers for iterating through arrays in for loops, so I'm not sure what is causing it here.
static int findHigh(int[] arr) {
int high = arr[0];
for(int i = 0; i < arr.length; i++) {
if(arr[i] >= high)
high = arr[i];
}
return high;
}
static int findLow(int[] arr) {
int low = arr[0];
for(int i = 0; i < arr.length; i++) {
if(arr[i] <= low)
low = arr[i];
}
return low;
}
static Triple<Integer,Integer,Integer> findMaxSubarray(int[] arr, int low, int high){
if(high == low)
return (new Triple<> (low, high, arr[low])); //error here
else {
int mid = low + (high - low) / 2;
Triple<Integer,Integer,Integer> l = findMaxSubarray(arr, low, mid); //error here
Triple<Integer,Integer,Integer> r = findMaxSubarray(arr, mid + 1, high);
Triple<Integer, Integer, Integer> c = findMaxCrossingArray(arr, low, mid, high);
if(l.getLast() >= r.getLast() && l.getLast() >= c.getLast())
return (new Triple<> (l.getFirst(), l.getMiddle(), l.getLast()));
else if(r.getLast() >= l.getLast() && r.getLast() >= c.getLast())
return (new Triple<> (r.getFirst(), r.getMiddle(), r.getLast()));
else
return (new Triple<> (c.getFirst(), c.getMiddle(), c.getLast()));
}
}
static Triple<Integer,Integer,Integer> findMaxCrossingArray(int arr[], int low, int mid, int high){
int leftSum = Integer.MIN_VALUE, leftMax = 0;
int rightSum = Integer.MIN_VALUE, rightMax = 0;
int sum = 0;
for(int i = mid; i >= low; i--) {
sum += arr[i];
if (sum > leftSum) {
leftSum = sum;
leftMax = i;
}
}
sum = 0;
for(int j = mid; j <= high; j++) {
sum += arr[j];
if (sum > rightSum) {
rightSum = sum;
rightMax = j;
}
}
return (new Triple<> (leftMax, rightMax, leftSum + rightSum));
}
public static Triple<Integer,Integer,Integer> getMaxSubarray(int[] arr){
int high = findHigh(arr);
int low = findLow(arr);
return(findMaxSubarray(arr, low, high)); //error here
}
When you use
return (new Triple<> (low, high, arr[low]));
It take arr[index] in the third place, so if your lowest number is -25 it is causing bug with out of bonds, cause your index is -25.
Trying to understand this question a bit more. Currently I need to return the sum of all the values that lie with a range either low or high within an array. Currently I have got this far (see code below), however I am stuck on what to do next. Any help?
public static int sumrange(int[] data, int low, int high) {
int sum = 0;
if (data == null || data.length == 0) {
return 0;
}
for (int i = 0; i < data.length;) {
if (i < low) {
sum = sum + data[i];
return sum;
}else if (i > high)
sum = sum + data[i];
return sum;
}
return 0;
}
I have been trying to figure out why in the binary search code of Java, we have used '<=' rather than simply using a '=='. Is it some sort of optimization?
The following piece of code is from Class: java.util.Arrays, method: binarySearch0()
Code:
private static int binarySearch0(long[] a, int fromIndex, int toIndex, long key) {
int low = fromIndex;
int high = toIndex - 1;
while(low <= high) {
int mid = low + high >>> 1;
long midVal = a[mid];
if (midVal < key) {
low = mid + 1;
} else {
if (midVal <= key) { // Why here have we used '<=' rather than '=='
return mid;
}
high = mid - 1;
}
}
return -(low + 1);
}
Your code differs from the one used within the JDK (http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/be44bff34df4/src/share/classes/java/util/Arrays.java#l1825), so I can only assume that you used some kind of decompiler to arrive at your source code.
The original source code is readable and clearly communicates the intention:
private static int binarySearch0(long[] a, int fromIndex, int toIndex,
long key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
long midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
Now if you look at the if statements:
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
you could rewrite it as (still the same code as before):
if (midVal < key) {
low = mid + 1;
} else {
if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
Now you can change the comparison in the second if and swap the then and else branches of that statement:
if (midVal < key) {
low = mid + 1;
} else {
if (midVal <= key) {
return mid; // key found
}
high = mid - 1;
}
This code is functionally equivalent but the intention is no longer visible.
You can use '==' too. As if midVal < key, it will never go to the else part.
This question already has an answer here:
What does "possible lossy conversion" mean and how do I fix it?
(1 answer)
Closed 3 years ago.
/**
*
* #param b is an array
* #param x is the element for which I want to search the lower bound
* #param n is the length of the array
* #return high if element not found or mid - 1 if found
*/
static long searchMe(long b[], long x, long n){
long low = 0, high = n, mid=0;
while(low<=high){
mid = (low+high)/2;
if(b[mid] == x){
if(mid > 0 && b[mid-1] == x) high = mid-1;
else return mid-1;
}
else if(b[mid] < x) low = mid + 1;
else high = mid - 1;
}
// System.out.println(low + " == " + high);
return high;
}
You are using mid as an index of an array, but mid is long. The index of an array is always an int. You can try this.
static long searchMe(long b[], long x, long n) {
long low = 0, high = n;
int mid = 0; // CHANGED FROM long TO int
while (low <= high) {
mid = (int) ((low + high) / 2); // CAST to int
if (b[mid] == x) {
if (mid > 0 && b[mid - 1] == x)
high = mid - 1;
else
return mid - 1;
} else if (b[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
// System.out.println(low + " == " + high);
return high;
}
I am trying to get the first occurrence of the number 5.The answer should be 2 in this case but i am getting 3 here.
public static void main(String[] args) {
int A[] = {1, 3, 5, 5, 5, 17, 20};
int index = BinarySearch(A, 5);
System.out.println(index);
}
public static int BinarySearch(int[] A, int x) {
int low = 0;
int high = A.length - 1;
while (low <= high) {
//(low + high) / 2
int mid = low + (high-low)/2; // more optimal -> low + (high-low)/2 (avoid integer overflow)
if (x == A[mid]) {
return mid;
} else if (x < A[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
When you find the value you are looking for, you return the mid index immediately without checking if there are smaller indices having the same value.
You have to continue searching :
public static int BinarySearch(int[] A, int x) {
int low = 0;
int high = A.length - 1;
int mid = -1;
while (low <= high) {
mid = low + (high-low)/2;
if (x <= A[mid]) { // this ensures you keep searching for the first index having
// the number you are looking for
//
// changing x <= A[mid] to x < A[mid] will give you the
// last index having the number you are looking for instead
high = mid - 1;
} else {
low = mid + 1;
}
}
if (mid >= 0 && x == A[mid]) {
return mid;
}
return -1;
}