Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException in Finding Max Element - java

Whenever I am trying to run this code, it gives me out of bound exception. Can anyone point me out what's wrong with it.
package com.programs.interview;
import java.util.Scanner;
public class FindMaxNumInArray {
public static void main (String[] args)
{
Scanner scan = new Scanner (System.in);
System.out.print("Enter the size of the array: ");
int arraySize = scan.nextInt();
int[] myArray = new int[arraySize];
System.out.print("Enter the " + arraySize + " values of the array: ");
for (int i = 0; i < arraySize; i++)
myArray[i] = scan.nextInt();
for (int j = 0; j < arraySize; j++)
System.out.println(myArray[j]);
System.out.println("In the array entered, the larget value is "+ maximum(myArray,arraySize) + ".");
}
public static int maximum(int[] arr, int Arraylength){
int tmp;
if (Arraylength == 0)
return arr[Arraylength];
tmp = maximum(arr, Arraylength -1);
if (arr[Arraylength] > tmp)
return arr[Arraylength];
return tmp;
}
}
Output
Enter the size of the array: 5 Enter the 5 values of the array: 1 2 3
4 5 1 2 3 4 5 Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 5 at
com.programs.interview.FindMaxNumInArray.maximum(FindMaxNumInArray.java:26)
at
com.programs.interview.FindMaxNumInArray.main(FindMaxNumInArray.java:17)

This is the problem:
if (arr[Arraylength] > tmp)
Valid array indexes go from 0 to length-1 inclusive. array[array.length] is always invalid, and on the initial call, ArrayLength is equal to arr.length.
It's not clear why you're using recursion at all, to be honest. An iterative solution would be much simpler - but you'll need to work out what you want to do if the array is empty.
EDIT: If you really want how I would write the recursive form, it would be something like this:
/** Returns the maximum value in the array. */
private static int maximum(int[] array) {
if (array.length == 0) {
// You need to decide what to do here... throw an exception,
// return some constant, whatever.
}
// Okay, so the length will definitely be at least 1...
return maximumRecursive(array, array.length);
}
/** Returns the maximum value in array in the range [0, upperBoundExclusive) */
private static int maximumRecursive(int[] array, int upperBoundExclusive) {
// We know that upperBoundExclusive cannot be lower than 1, due to the
// way that this is called. You could add a precondition if you really
// wanted.
if (upperBoundExclusive == 1) {
return array[0];
}
int earlierMax = maximumRecursive(array, upperBoundExclusive - 1);
int topValue = array[upperBoundExclusive - 1];
return Math.max(topValue, earlierMax);
// Or if you don't want to use Math.max
// return earlierMax > topValue ? earlierMax : topValue;
}

you can't access
arr[Arraylength]
the last element would be at
arr[Arraylength -1]
for example if you have
int arr[] = new int[5];
then the elements would be at 4, because index starts from 0
arr[0], arr[1], arr[2], arr[3], arr[4]

Your issue is in the following piece of code:
if (arr[Arraylength] > tmp)
return arr[Arraylength];
Indexes start at 0, so you will be out of bound for an array with 5 elements [1,2,3,4,5] indexes: [0,1,2,3,4].

I would use a plain loop. Java doesn't do recursion particularly well.
public static int maximum(int[] arr) {
int max = Integer.MIN_VALUE;
for(int i : arr) if (i > max) max = i;
return max;
}

here
System.out.println("In the array entered, the larget value is "+ maximum(myArray,arraySize) + ".");
you are passing the arraysize where in maximum method you are returning arr[Arraylength] which giving ArrayIndexOutOfBound so change either in calling maximum(yArray,arraySize-1) or return arr[Arraylength-1] statement.

Related

Incorrect conversion and display in the output

My code should find the smallest digit in a given number, and indicate its position. If there are several such digits, then indicate all positions.
For example,
when entering 1231
Output: position - [1 4]
The digit that is the minimum in the entered number does not need to be displayed. As it seems to me, my problem is in the output.
Help me figure out how to convert correctly, or rather display the number's position.
As I understand it, the whole problem is in the line
Integer[] s1 = getMinPos(s);
import java.util.Scanner;
import java.util.LinkedList;
public class test1 {
public static void main(String[] args) {
Scanner text = new Scanner(System.in);
System.out.println("Enter: ");
int k = text.nextInt();
String s = Integer.toString(k);
Integer[] s1 = getMinPos(s);
System.out.println("position - " + s1);
}
static Integer[] getMinPos(String num) {
LinkedList<Integer> list = new LinkedList<>();
int maxVal = -1, counter = 1;
for (char a : num.toCharArray()) {
if (maxVal < a) {
maxVal = a;
list.clear();
}
if (a == maxVal) {
list.add(counter++);
}
}
return list.toArray(new Integer[0]);
}
}
You main issue is this line:
System.out.println("position - " + s1);
You cannot print an array like that. When you try to print an array variable, it prints the object reference. Not the elements of the array. You need something like this to print it.
System.out.println("position - ");
for (int i : s1) {
System.out.print(i + " ");
}
Check how it prints the array by iterating through the elements.
When you print using this, you may find that your logic is not finding the position of the minimum value, but the position of the maximum value.
If you want to find the positions of the minimjum digit, the logic should be something like this:
static Integer[] getMinPos(String num) {
LinkedList<Integer> list = new LinkedList<>();
int minValue = '9' + 1, counter = 1;
for (char a : num.toCharArray()) {
if (a < minValue) {
minValue = a;
list.clear();
list.add(counter);
} else if (a == minValue) {
list.add(counter);
}
counter++;
}
return list.toArray(new Integer[0]);
}
Notice here that since you are comparing the char values, I have used the char value of 9 ('9') and added 1 to make sure that the starting minValue is always higher than any digit.
Then, there's another issue where you do not add the first index to your list. I've fixed that too.
You also do not increase the counter when you find a value greater than a. (Or in the fixed version, when the value of a is greater than minValue. That will be causing a bug, where your program will return incorrect indexes. So, the incrementing the counter is moved out from the if-else blocks.

Twin array Find a Minimum value from each Array index must be different

You are given two arrays A and B each containing n, integers. You need to choose exactly one number from A and exactly one number from B such that the index of the two chosen numbers is not same and the sum of the 2 chosen values is minimum.
Your objective is to find and print this minimum value.
For example in the image shown below is the minimum sum.
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
static int twinArrays(int[] ar1, int[] ar2){
// Complete this function
int minAr1 = ar1[0];
int minAr2;
int index = 0;
for(int i =0; i<ar1.length;i++) {
if(ar1[i]<minAr1) {
minAr1 = ar1[i];
index = i;
}
}
if(index == 0) {
minAr2 = ar2[1];
}else {
minAr2 =ar2[0];
}
for(int j=0;j<ar2.length;j++) {
if(j!=index && minAr2>ar2[j]) {
minAr2 =ar2[j];
}
}
return minAr1+minAr2;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
if(n>=2 && n<=1000000) {
int[] ar1 = new int[n];
for(int ar1_i = 0; ar1_i < n; ar1_i++){
int temp1 = in.nextInt();
if(temp1>=1&&temp1<=1000000) {
ar1[ar1_i] = temp1;
}
}
int[] ar2 = new int[n];
for(int ar2_i = 0; ar2_i < n; ar2_i++){
int temp2 = in.nextInt();
if(temp2>=1&&temp2<=1000000) {
ar2[ar2_i] = temp2;
}
}
int result = twinArrays(ar1, ar2);
System.out.println(result);
}
}
}
i have Implemented that is working fine but still something is missing so some test case failing could anyone give me some clue and hint to optimize my code if you find any defect in this code
Your code works by finding the minimum value from the first array, then finding the minimum value from the second array that isn't at the same position of the minimum in the first array. The problem with this approach is that it isn't guaranteed to find the overall minimum sum. For example, consider these small arrays:
[0, 1], [0, 100]
Here, if you take the minimum value of the first array (0) and the minimum value of the second array that isn't at the same position (100), you get the sum 100. However, the correct sum to pick is the smallest value from the second array (0) and the second-smallest value from the first array (1) for a total of 1.
One observation that's useful here is that the minimum-sum pair must be one of the following:
The sum of the smallest values from each array.
The sum of the smallest value from one array and the second-smallest value from the other.
Your solution is on the right track here, except you don't consider taking the smallest from the second array and the second smallest from the first. Try editing your code to account for that case.
One simple observation is that if minimum elements from both arrays are at different position, Sum of both elements would be an answer so after sorting answer in this case would be A[0]+B[0], but if both are at the same position, there are two possibilities for answer after sorting both the arrays.
Suppose we have two arrays A and B which are sorted in increasing order. Then there are two possible answers and the actual answer would be minimum of them.
Take minimum possible number from array A so that number would be A[0] and now find the minimum possible number from array B such that index of that element is not equal to 0 so best possible choice would be B[1]. Therefore answer in this case is A[0]+B[1].
Another possibility is that we consider minimum possible number from array B first and then go to choose a number from array A so here those numbers would be A[1] and B[0] respectively and thus answer in this case is A[1]+B[0].
Now for the final answer, we can take minimum of both these possible answers.
Final_Answer = min(A[0]+B[1],A[1]+B[0]);
If you don't want to sort the Arrays due to tight time constraint. You can just keep track of First and Second minimum element of both arrays and use it in place of A[0],A[1] in above equation respectively.
A sample code using first and second minimum,
static int twinArrays(int[] ar1, int[] ar2){
int first_minimum_ar1 = Integer.MAX_VALUE;
int second_minimum_ar1 = Integer.MAX_VALUE;
int index_ar1=-1;
int first_minimum_ar2 = Integer.MAX_VALUE;
int second_minimum_ar2 = Integer.MAX_VALUE;
int index_ar2=-1;
for(int i=0;i<ar1.length;i++)
{
int element = ar1[i];
if(first_minimum_ar1>=element)
{
second_minimum_ar1=first_minimum_ar1;
first_minimum_ar1=element;
index_ar1=i;
}
else if(second_minimum_ar1>element)
{
second_minimum_ar1=element;
}
}
for(int i=0;i<ar2.length;i++)
{
int element = ar2[i];
if(first_minimum_ar2>=element)
{
second_minimum_ar2=first_minimum_ar2;
first_minimum_ar2=element;
index_ar2=i;
}
else if(second_minimum_ar2>element)
{
second_minimum_ar2=element;
}
}
if(index_ar2!=index_ar1)
return first_minimum_ar1+first_minimum_ar2;
return Math.min(first_minimum_ar1+second_minimum_ar2,first_minimum_ar2+second_minimum_ar1);
}
What I did was, sort one array(ar1) in ascending order(take ar[0]) and the other in descending order(ar2) and then take (ar2[ar2.length-1]).
class TwinArray{
static int twinArrays(int[] ar1, int[] ar2){
Arrays.sort(ar1);
Integer[] Ar2 = new Integer[ar2.length];
for (int i=0;i<ar2.length;i++)
Ar2[i]=ar2[i];
Arrays.sort(Ar2,Collections.reverseOrder());
System.out.println(Ar2[Ar2.length-1]);
return (ar1[0]+Ar2[Ar2.length-1]);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] ar1 = new int[n];
for(int ar1_i = 0; ar1_i < n; ar1_i++){
ar1[ar1_i] = in.nextInt();
}
int[] ar2 = new int[n];
for(int ar2_i = 0; ar2_i < n; ar2_i++){
ar2[ar2_i] = in.nextInt();
}
int result = twinArrays(ar1, ar2);
System.out.println(result);
}
}
This one will probably pass all of your test cases.
Runtime Complexity ~ o(n)
static int twinArrays(int[] ar1, int[] ar2){
int ar1Minimum = Integer.MAX_VALUE , ar1MinIndex = -1;
int ar1SecondMin = Integer.MAX_VALUE ;
//Get the element with minimum value and index
for(int i = 0 ; i < ar1.length ; ++i){
if(ar1Minimum > ar1[i]){
ar1Minimum = ar1[i]; ar1MinIndex = i;
}
}
//Get the second minimum
for(int i = 0 ; i < ar1.length ; ++i){
if(ar1SecondMin > ar1[i] && i!=ar1MinIndex){ // i != ar1MinIndex = Important to avoid duplicate minimum values [1,1,2,4] min = 1 , secondMin = 2 and not 1
ar1SecondMin = ar1[i];
}
}
int ar2Minimum = Integer.MAX_VALUE , ar2MinIndex = -1;
int ar2SecondMin = Integer.MAX_VALUE ;
for(int i = 0 ; i < ar2.length ; ++i){
if(ar2Minimum > ar2[i]){
ar2Minimum = ar2[i]; ar2MinIndex = i;
}
}
for(int i = 0 ; i < ar2.length ; ++i){
if(ar2SecondMin > ar2[i] && i != ar2MinIndex){
ar2SecondMin = ar2[i];
}
}
if(ar1MinIndex != ar2MinIndex){
return ar1Minimum + ar2Minimum;
}
return Math.max((ar1Minimum + ar2SecondMin), (ar1SecondMin + ar2Minimum));
}

How to find the highest and the lowest number stored in an array? [duplicate]

This question already has answers here:
How to find max and min value [duplicate]
(3 answers)
Closed 6 years ago.
I am trying to print the highest and lowest integer number stored in an array. I am able to print the highest but for the lowest I am not getting the correct result.
Consider my two classes below :
class ArrayUtilityNew
{
public static int findMaxMin(int a[])
{
int n=a.length;
int n2=n-1;
int minNo=0;
int count=0;
int maxNo=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i]<a[j])count++;
}
//This gives the highest no. if the count is 0
if(count==0)
{
maxNo=a[i];
}
//Lowest no. shall be gained here if the count is greater
// than the no of elements in the array
// if(count>n)
// {
// minNo=a[i];
// }
count=0;
}
return maxNo;
}
}
class ArrayInteractionsNew
{
public static void main(String arr[])
{
int one[]={3,20,1999,2,10,8,999};
int answer=ArrayUtilityNew.findMaxMin(one);
System.out.println("The highest no in the array is "+answer);
}
}
Is the logic behind the second if not correct or is there some other mistake?
How can it be corrected?
You could return an int[] of min and max. Start with an array of two elements, loop over the array1 like
public static int[] findMinMax(int[] a) {
int[] result = { Integer.MAX_VALUE, Integer.MIN_VALUE };
for (int i : a) {
result[0] = Math.min(result[0], i);
result[1] = Math.max(result[1], i);
}
return result;
}
The result will be an array with the first element being the minimum value2. Then to test it,
public static void main(String[] args) {
int[] arr = { 3, 20, 1999, 2, 10, 8, 999 };
int[] minMax = findMinMax(arr);
System.out.printf("%s: min=%d, max=%d%n",
Arrays.toString(arr), minMax[0], minMax[1]);
}
And I get (as I would expect)
[3, 20, 1999, 2, 10, 8, 999]: min=2, max=1999
1Here, with a for-each loop.
2And the second element being the maximum.
I think your solution is way too complex... A better and more efficient solution would be this:
int n=a.length;
int minNo=a[0];
int maxNo=a[0];
for(int i=1;i<n;i++)
{
if(a[i] > maxNo) {
maxNo = a[i];
} else if(a[i] < minNo) {
minNo = a[i];
}
}
// do whatever you want with maxNo and minNo
Also an even more efficient (in the code size way) way would be to use lists or streams because you can do one-liners with it.
EDIT: less ambiguous code and explanations about efficiency
Your answer is n^2. To find min and max it only needs to be order n.
In other words you only need to look linear.
Do a loop that looks through the list once. Keep track of min and max as you go. Initially set min = maxvalue and max=minvalue. When you find a value smaller than min, it becomes the new min.
Here is an example in pseudo code.
min = max_int
max = min_int
for (i=0; i < array.length; i++)
if array[i] < min
min = array[i]
if array[i] > max
max = array[i]
Your approach, if it even works, is needlessly complicated.
Create two variables: minNo and maxNo.
Set minNo = Integer.MAX_VALUE and maxNo = Integer.MIN_VALUE.
Loop through the array. If the element is >= maxNo, assign its value to maxNo. Also (not instead -- i.e., not else if!), if the element is <= minNo, then assign its value to minNo.
After the loop, minNo and maxNo will be correctly assigned.
public static void minMax(int []arr){
int min = arr[0];
int max = arr[0];
for(int i=1; i<arr.length; i++){
min = Math.min(min,arr[i]);
max = Math.max(max,arr[i]);
}
//do whatever you want with the max and min
}
Thanks to the Streaming API in java8, this is a two-liner:
int[] array = new int[] {5,7,2,9,10,24,3,23};
int min = IntStream.of(array).min().getAsInt();
int max = IntStream.of(array).max().getAsInt();
Or as a more efficient 3-liner:
Arrays.parallelSort(array);
int min = array[0];
int max = array[array.length -1];

How to remove the last input element in an array?

For this program, I have a user input elements into a 5 space array using the private static void add() method. After adding these elements, the user is then able to use the private static void delete() method which allows them to input a number present in the array that they wish to remove. When entering numbers to remove, the program works perfectly fine unless I try to remove the last number for the currentSize of the array. For example, if I have an array with the following indexes and values:
0. = 1
1. = 2
2. = 3
3. = 4
4. = <empty>
The currentSize of the array is currently 4. If I try to remove value 4 in index 3, the program will not remove value 4. If I attempt to remove values 3, 2, or 1 after trying to remove value 4, these values will not remove either. On the other hand if I want to remove any of the values below value 4 first, i.e) values 1, 2, and 3, the program works correctly until I try to remove value 4 in index 0. If I attempt to remove value 4 at this point, nothing is removed. If I try to add a value, say 1, after attempting to remove value 4, value 4 is replaced with value 1. If I attempt to remove value 4 twice at index 0 and then attempt to add a new value, I get an IndexOutOfBoundsException: -1 . I believe that this has something to do with currentSize-- decrementing when it is not suppose to in the remove element algorithm present in the private static void delete() method. If anyone has a solution for this it would be greatly appreciated, thank you. The program is posted below. I have commented the section of the private static void delete() method that is giving me issues. This is the stack trace that I am getting:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at ArrayManager.add(ArrayManager.java:35)
at ArrayManager.main(ArrayManager.java:216)
/**
* A class that contains methods to carry out the Add, Update, Delete, Drop, Resize, and End commands to alter the state of an array with 5 integers.
*/
public class ArrayManager
{
// Array of 5 integers to be modified
private static int [] values = new int [5];
private static int currentSize = 0;
private static int position = 0;
//private static int index = 0;
static Scanner in = new Scanner(System.in);
/**
* A method that inserts an entered value into the array as long as it is between 1 and 99. If the array is full, an error message will be printed explaining that the array is full.
*/
private static void add()
{
System.out.println("Enter values between 1 and 99, inclusive that you would like to add to the array.");
if(in.hasNextInt())
{
int n = in.nextInt();
if(n >= 1 && n <= 99)
{
if(currentSize < values.length)
{
values[currentSize] = n;
currentSize++;
}
else
{
System.out.println("ERROR: The array is currently full.");
}
}
else
{
System.out.println("ERROR: The number entered must be between 1 and 99, inclusive.");
}
}
else
{
System.out.println("ERROR: String has been entered. Enter an Integer.");
}
}
/**
* A method that asks the user to enter a value they wish to delete in the array. The following values are then shifted down in index in the array. If the value chosen does not exist in the array, an error message is displayed explaining that the value entered does not exist in the array.
*/
private static void delete()
{
int n = 0;
System.out.println("Please enter the value in the array that you wish to remove.");
if(in.hasNextInt())
{
n = in.nextInt();
for(position = 0; position < values.length; position++)
{
if(values[position] == n)
{
// The stack trace points me back to this section of code which removes the specified value in the values array.
for(int i = position + 1; i < currentSize; i++)
{
values[i - 1] = values[i];
values[i] = 0;
}
currentSize--;
break;
}
else if(position == values.length - 1)
{
System.out.println("ERROR: The value entered does not exist in the array.");
}
}
}
else
{
System.out.println("ERROR: String has been entered. Enter an Integer.");
}
}
/**
* A method that prints out the modified array.
*/
public static void printArray()
{
System.out.println("* Current Array Contents *");
for(int i = 0; i < values.length; i++)
{
if(values[i] != 0)
{
System.out.println(i + ". = " + values[i]);
}
else if(values[i] == 0)
{
System.out.println(i + ". = <empty>");
}
}
}
The corner case where position is the index of last element of the values array, is not handled properly. In such a scenario, the code starts to iterate the elements from the next index in order to shift all the elements by 1 position and the condition is not met by the condition in for loop.
for(int i = position + 1; i < currentSize; i++)
for(int i = position + 1; i < currentSize; i++)
{
values[i - 1] = values[i];
values[i] = 0;
}
The solution would be to check for that condition and handle it explicitly.
if(values[position] == n ) {
if( position != values.length - 1 ) {
for(int i = position + 1; i < currentSize; i++)
{
values[i - 1] = values[i];
values[i] = 0;
}
} else {
values[i] = 0;
}
currentSize--;
break;
}

Finding the largest number in an array of integers

I am trying to recursively find the largest element in an array. The user has to input the number of elements that the array will have. My error is that if that the list does not have an element which is larger than the number of elements in the list, the output of the largest number will be the number of elements in the list. eg: array of 5 integers containing {1 1 1 2 3}. the answer will be 5 and not 3.
import java.util.*;
public class test7 {
public static int findLargest(int[] a, int max) {
int i=0, j=0, tempmax=0;
if (a.length == 1) return a[0]>max ? a[0]:max;
else if(max < a[i]){
max = a[i];
int[] tempArr = new int[a.length -1];
for (i=1; i<a.length; i++){
tempArr[j] = a[i];
j++;
}
tempmax = findLargest(tempArr, max);
return tempmax;
}
else{
int[] tempArr = new int[a.length -1];
for (i=1; i<a.length; i++){
tempArr[j] = a[i];
j++;
}
tempmax = findLargest(tempArr, max);
return tempmax;
}
}
public static void main(String[] args) {
int[] values = new int[100];
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number of elements in your list: ");
int x = scan.nextInt();
if(x>1 || x<100){
for (int i=0; i<=(x-1); i++){
System.out.print("Enter your number: ");
System.out.println();
values[i] = scan.nextInt();
}
System.out.println();
System.out.println("The largest number is: "+findLargest(values, x));
}
else System.out.println("The maximum number of elements must be less than 100");
}
}
You call your method with:
System.out.println("The largest number is: "+findLargest(values, x))
This tells it to assume the largest number is x and try to find anything in the list that is greater than that. Of course, this produces the exact problem you described.
In general, when finding a maximum number, you want to initialize your candidate to the lowest number possible, or to the first number in your array.
If you initialize to the lowest number possible (Integer.MIN_VALUE) then as soon as you start your algorithm, the first number will definitely be bigger than it and will be chosen as the next candidate for maximum.
If you initialize to the first item in your array, then if that number is the highest, all well and good. If it is not, then when you encounter the next higher number, it will become the candidate, and all is good.
Which one you choose is up to you (and depends also on whether an empty array is possible), but the thing to remember is never to select an initial candidate that might be greater than all the elements in the array.
Try this working example:
public static void main(String[] args)
{
int[] numbers = {2, 5134, 333, 123, 8466};
int largest = numbers[0];
for(int i = 1;i<numbers.length;i++)
{
largest = Math.max(largest, numbers[i]);
}
System.out.println("Largest number: "+largest);
}
As a method that would look like this:
public static int max(int first, int... more)
{
for(int element:more)
{
first = Math.max(first, element);
}
return first;
}
You can then call it using something like max(1,23,564,234,543);

Categories

Resources