Error finding largest randomly generated double in ArrayList Java - java

I'm trying to get a program to work where I generate 1,000,000 random numbers between 0 and 1 and then find and print the largest number.
I've got the generator to work and managed to insert each double generated into an ArrayList but I cannot seem to figure out how to find the largest number in the list. At the moment the current code throws the error "java.lang.IndexOutOfBoundsException".
This is all probably due to me being new to the ArrayList and not being fluent with its commands and how it works but I would really appreciate some help on what I'm doing wrong here as I've been stuck for a while.
import java.util.ArrayList;
import java.util.Random;
public class milran {
public static void main(String[] args) {
Random r = new Random();
ArrayList<Double> myList = new ArrayList<Double>();
for (int i = 1; i<=1000000; i++){
double randomValue = 0.0+(1.0-0.0)*r.nextDouble();
myList.add(randomValue);
}
double max = myList.get(1);
for (int z=2; z<=myList.size(); z++){
double test = myList.get(z);
if (test>max){
max = test;
}
}
System.out.println(max);
}
}

First of all take a look at the docs for java.util.Collections and java.util.ArrayList.
Secondly, the ArrayIndexOutOfBoundsException is being triggered by this...
for (int z=2; z<=myList.size(); z++){
double test = myList.get(z);
...
}
This is because array indexing starts at 0, therefore the last element is myList.size() - 1. In other words, when z = myList.size(), it is out of bounds.
Also, in your first for loop, you are using i = 1; 1 <= 1000000. It makes much more sense to use i = 0; i < 1000000 as you can use i to touch each element in an array (or list).
for( i = 0; i < 1000000; i++ )
{
// do something with myArray[i]
}
Here's what I would do after the values have been inserted...
Sort the array: Collections.sort(myList);
Retrieve the last element: System.out.println( myList.get( myList.size() - 1 ) );
...and that's it.
If you need to implement the actual sort yourself then i'd consider using a primitive double array (double[]) rather than a Collection.
Otherwise, if you are using a collection, you can use a foreach loop.
for( Double d : myList ) // for each Double 'd' in myList
{
// do something with d
}
N.B. Another potential issue with this line in the second loop
double test = myList.get(z);
This automatic conversion from Double (object) to double (primitive) is called unboxing. There will be a performance cost, especially when repeated a million times. In the first loop you are converting the other way (autoboxing) – also a million times.

ArrayList start count its elements from 0. You need to replace myList.get(1) to myList.get(0), int z=2 to int z=1 and z<=myList.size() to z<myList.size().

This line: for (int z=2; z<=myList.size(); z++) { is wrong. It should be for (int z=1; z<myList.size(); z++) {.
This is because arrays and lists are 0 based, so a list of size 2 has 2 elements - index 0 and index 1. Currently you try to index into the element number equal to the size, which does not exist.
Along the same line, myList.get(1); should be myList.get(0);.
This is unrelated to your problem, but this line 0.0+(1.0-0.0)*r.nextDouble(); can be much more easily written as r.nextDouble();. I'm not sure what you were trying to do by doing 0 + 1 - 0.

As others have already pointed out, you have an error in your for-loop condition that causes the index to go out-of-bounds.
One way that you can avoid this in the future is by using Java's for-each loop syntax instead of trying to manage the index yourself.
for (Double test : myList) {
if (test>max){
max = test;
}
}
This syntax makes your intent much clearer than the traditional indexed for syntax and removes a point of potential error (managing the index and the bounds of the list) from your hands.

Related

Java finding all combos in array that add up to specific number [duplicate]

This question already has an answer here:
Finding all the number combos in array that add up to input number
(1 answer)
Closed 6 years ago.
I'm currently working on the following question from a interviewing book:
You are given a random array of 50 unique integers ranging from 1 to 100 inclusive. Write a method using Java that takes in a positive integer as a parameter and returns an array of all the number combinations that add up to that value.
For example, given an array of integers [3,6,1,9,2,5,12] and being passed the integer value 9, you would return [[3,6],[6,1,2],[9],[3,1,5]]. Order of returning the results in the array does not matter, though you should return unique sets (ie. [6,3] and [3,6] are the same and only one should be returned). Also, the individual results should be in the order they are found (ie [6,1,2] should be returned, not [1,2,6]).
I've made decent progress on it, but I fear I may solving this the wrong way.
import java.util.*;
public class findCombinations {
public static void main(String[] args) {
int number;
int[] list = new int[10];
Scanner reader = new Scanner(System.in);
//fill the array
for (int i = 0; i < list.length; i++) {
number = (int)(Math.random() * 10) + 1;
list[i] = number;
for (int j = 0; j < i; j++) { //remove duplicates
if (list[i] == list[j]) {
i--;
break;
}
}
}
Arrays.sort(list);
//test output
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
System.out.println("Enter a number: ");
int input = reader.nextInt();
ArrayList<Integer> trimmedList = new ArrayList<Integer>();
//cut out the numbers that are impossible to use
for (int i = 0; i < list.length; i++) {
if (list[i] <= input) {
trimmedList.add(list[i]);
}
}
//test output
printList(trimmedList);
ArrayList<Integer> comboList = new ArrayList<Integer>();
System.out.println("Finding combinations...");
for (int i = 0; i < trimmedList.size(); i++) {
int current = trimmedList.get(i);
if (current == input) { System.out.println(current); }
else if (current < input) {
comboList.add(current);
if (isCombo(comboList, input)) {
printList(comboList);
}
else { continue; }
}
else { continue; }
}
}
public static boolean isCombo(ArrayList<Integer> list, int input) {
ArrayList<Integer> combo = new ArrayList<Integer>();
int sum = 0;
for (int i : list)
sum += i;
if (sum == input) { return true; }
else { return false; }
}
public static void printList(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
}
}
I know this is incomplete but I wanted to ask if anyone had any suggestions or improvements I could make on this? I sorted my list and trimmed out all the integers that won't possibly be used, but now the hard part is finding all the combos.
There are many different approaches to solve this problem, each with their own merits, so I wouldn't worry too much about whether your answer is the 'right' one or not...so long as it actually solves the problem! Also, an interviewer will likely be more interested in your thought-process, and the strategies you use, rather than a 100% perfect solution written in the span of a few minutes on a whiteboard.
Here's a couple of things to consider:
As you noticed, you can immediately eliminate any integers larger than your target value.
You're essentially generating arbitrarily-sized subsets of your starting array—so Set is likely the most useful data type to work with. {2, 3} and {3, 2} should be seen as identical when you're generating your response set.
Integer partitioning is an NP-Complete problem. It's hard. I think you've taken the correct approach of starting with the array, rather than with the target value.
There are many algorithms for generating combinations of integers from a larger set. Check out this SO answer for a few of them. You can generate k sized combinations from your (already-filtered) starting set, for k from 1-50.
Actually...there are more direct ways to get the power set of your starting set. Consider the inherent structure of a power set (shown below). By enumerating a few examples, you'll notice a natural recurrence in your strategy for identifying the subsets.
As you're generating these combinations, discard any whose elements don't sum to your target value.
Image Source: https://en.wikipedia.org/wiki/Power_set
Since this is a learning exercise, you will benefit most if you can solve this for yourself. So ...
Hints:
Sorting the numbers first is on the right track
I would use recursion to iterate the solutions. Given a partial sum, only numbers less than a certain number are possible candidates to be added to the sum ...
Work out the algorithm in your head >before< you start coding it.
And I agree with what #nbrooks says on the topic of what the interviewers are looking for. You need to be able to think ... and explain your thinking to the interviewer ... at the algorithmic level. That is what will distinguish the excellent candidates from the ordinary ones.
I realize generating your array of random numbers is not part of the problem statement, but I think your difficulties begin here.
First of all, use a Set<Integer> type collection to collect your generated numbers; break when the set reaches the desired size. If generated order is important, use a LinkedHashSet.
Set<Integer> origSet = new HashSet<Integer>(); // fill with random numbers
At some point, you have a list of numbers for which the order matters. Maintain this list as a List<Integer>. The list preserves the order of your original list so that you can produce the number combinations in the right order (i.e., 6 precedes 1, 1 precedes 2).
List<Integer> origList = new ArrayList<Integer>(origSet); // use indexOf method to find index of a number
You create a second list that is sorted; this list is the one used by your recursion algorithm.
List<Integer> sortedList = new ArrayList<Integer>(origList); // sort this
You don't need to trim the list because a recursive algorithm will trim any branch with no feasible solution.
A recursive algorithm can generate the combos in fewer lines of code. Reordering takes a few more lines.

organizing numbers in an array in Java [duplicate]

This question already has answers here:
Sort an array in Java
(19 answers)
Closed 9 years ago.
Im trying to organize random numbers in an array from least to greatest.
I came up with a loop which I thought should work but has a lot of logic errors.
for(int z=0; z<=999;z++){
for(w=1; w<=999;w++){
if(z<w){
if(numberArray[z]<numberArray[w])
temp=numberArray[w];
}
}
numberArray[z]=temp;
}
Can anyone tell me how to fix this or an algorithm of their own for doing this?
There are several ways you can sort an array in Java. Here I post but 3 of them : the core library, and 2 algorithms you can make on your own.
1 ) Core one: This is literally only one line of code. I would suggest using this - simple, and very efficient, compared to the below two solutions.
Arrays.sort(myArray);
2 ) Selection Sort : Find the lowest value in an array, move it to the first position, find the next lowest, move to 2nd position, etc.
public void selectionSort(Comparable[] a)
{
for(int index = 0; index < a.length; index++)
{
// find the smallest one in the array from index : end
int smallest = indexOfMin(a, index);
// swap the value at index and the value at the smallest one found
Comparable temp = a[smallest];
a[smallest] = a[index];
display.update();
a[index] = temp;
}
}
3 ) Insertion Sort : Inserts each element in the array into a growing sequence of sorted values and finishes at the end of the array.
public void insertionSort(Comparable[] a)
{
for(int i = 1; i < a.length; i++)
{
insert(a, i);
}
}
public void insert(Comparable[] a, int nextIndex)
{
int index = 0;
Comparable finalObject = a[nextIndex];
// Let us first find the first occurence of a comparable greater than our comparable
while(finalObject.compareTo(a[index]) > 0)
index++;
for(int i = (nextIndex-1); i >= index; i--)
a[i+1] = a[i];
a[index] = finalObject;
}
One liner:
Arrays.sort(numberArray);
Or greatest to least order:
Arrays.sort(numberArray, Collections.reverseOrder());
Or even better, use a Binary Search Tree that keeps its contents in sorted order, this is great for collections that are pretty dynamic, as the add operation is cheaper memory wise and time wise than a full in-place sort:
TreeSet<int> set = new TreeSet<int>();
set.add(10);
set.add(4);
set.add(11);
set.toString();
// prints 4, 10, 11
Arrays.sort() is a quick and easy way.
Also consider PriorityQueues if you need something a little more robust!
This link is another question on SO with a great answer.

Why am I getting ArrayIndexOutOfBoundsException?

So I got this assignment while my teacher is away, and basically I have to make a student project. The student has a name, marks, and average. To calculate the average I decided to store the marks inside a int[] array.
public void addQuiz(int m)
{
int l = (marks.length);
marks[l] = m;
}
int[] marks = new int[8];
But when I run the function:
student.addQuiz(90);
I get:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8
Any help?
I'm not sure what the int[8] part does but it was in the tutorial I followed and it would give me a null pointer without it. There are eight marks in total so I just made it 8.
You can't dynamically add things to an array. You should use an array list instead.
Arraylist<Integer> marks = new ArrayList<Integer>();
then in your addQuiz method:
public void addQuiz(int m) {
marks.add(m)
}
You'll probably also need to change your method for calculating the average a bit, but that should be trivial and I'll leave it to you.
The error says: ArrayIndexOutOfBoundsException: 8
You have an array with 8 elements, indexed from 0 to 7 (inclusive). This array has a length of 8, and you are actually trying to access marks[8], when you only can go up to 7.
In Java, Array index starts from '0'. so, you cannot access the index of the array equal to the length of the array.if your arrays length is '8', then the last index of the array is '7' not '8'. if you are trying to access the illegal index of the array, then ArrayIndexOutOfBoundException is thrown. the code should be changed to
public void addQuiz(int m)
{
int l = (marks.length); //assuming marks is an array of length '8'
marks[l-1] = m; //index is 7 now
}
To calculate the average, you need to sum up the contents of the array (provided all the values are of int values) and then divided by the lenght of the array
int sum = 0;
int avg = 0;
for(int i=0; i<array.length;i++){
sum =sum+array[i];
}
avg = sum/array.length;
Hope this gives an idea
Use Arraylist<Integer> and then you can add to the list dynamically
There is not index in this array for this marks[l] = m;. use marks[l-1] = m;
You can call this for loop in main for getting marks 8 times.
for(int i=0;i<8;i++)
student.addQuiz(<marks you want to enter>, i);
You can define addQuiz function like below
public void addQuiz(int m, int arrayIndex)
{
marks[arrayIndex] = m;
}
int[] marks = new int[8]; //this will be as it is
These are minimal changes. You can make your code better by passing array marks to addQuiz as a parameter. But this will also work, its just that this is not the best way to write code.

Reversing Integer Value

I cannot figure this out. This is for homework. I need to create a method that reverses an integer that is passed to it. I've now been able to fix the outofBounds error in the for loop thanks to everyone's input. The integer that is passed into the method can be of any length. And I have to return an integer instead of an array or string. But now I get an 'Unresolved compilation problem: Syntax error on token "[", Expression expected after this token' on the int u = backInt[]; line. But I have no idea what to put in the []'s. I haven't been able to find a way to convert an Integer array to an integer so I can pass the integer back, so I'm lost. Here is the code that I have so far:
public static int reverseIt(int x){
int y = String.valueOf(x).length();
int[] backInt = new int [y];
for(int z = 0; z < y; z++){
x %=10;
backInt[z] = x;
x /= 10;
}
int u = backInt[];
return u;
return -1;
}
You start with z=0 and end with z=y. That's y+1 times through the loop, but your array is correctly only y elements long, so the exception occurs on the last iteration of the loop when you try to write to the nonexistent element. By that time, though, x should already be zero because you've processed all y digits, so your stopping condition should be z<y instead of z<=y.
You're going too far in your loop. It should be:
for(int z = 0; z < y; z++) {
...instead.
Take the input 12 as an example. It's two characters long, so backInt has a length of 2. When you go through the loop, you're iterating through values of z of 0, 1, and 2. What's the value of backInt[2] when backInt only has two elements in it?
Edit: Your code will also break for, say, 2147483646, because your resulting integer will be too large for the Integer type. But that's beside the point here.
Java arrays are 0-indexed. What that means is that if you do int[] arr = new int[10], you create an integer array that can hold ten ints, and the first int is stored in arr[0], the second in arr[1], and the last in arr[10-1], which is arr[9].
To fix your code, change z <= y to z < y. In the future, just remember that if you create an array for n objects, then you can access them by arr[0], arr[1]... arr[n-1], but accessing arr[n] will throw an OutOfBounds exception.

Why is an array so much faster than an ArrayList?

Recently, I tried to solve Problem 23 of Project Euler. For that I first create a list of all abundant numbers, called abundants.
Next I iterate over this list and build another list of all sums of abundant numbers that are below a certain limit. Now I noticed something strange. I use a nested loop to iterate twice over the list. But if I use an array to store the sum it takes some seconds, if I add the sums to an ArrayList it takes hours. What's the reason for that? I thought the costly operation are the two nested loops, but it seems the costly operation is ArrayList#add. Any hints why this is the case?
Here the code for the array:
for (int i = 0; i < abundants.size(); i++) {
for (int j = 0; j < abundants.size(); j++) {
int tot = abundants.get(i) + abundants.get(j);
if (tot <= limit)
isSum[tot] = true;
}
}
}
Here the code for the ArrayList:
ArrayList<Integer> sums = new ArrayList<Integer>();
for (int i = 0; i < abundants.size(); i++) {
for (int j = 0; j < abundants.size(); j++) {
int s = abundants.get(i) + abundants.get(j);
if (!sums.contains(s) && s < limit) {
sums.add(s);
}
}
}
Your ArrayList implementation is O(n^3) whereas the other is O(n^2): sums.contains(...) has to traverse the entire sums list for every iteration of your inner loop.
I think rather that your problem is in ArrayList#contains, which has to traverse the whole list, thus raising your complexity to O(n^3), as opposed to O(n^2) of the program #1.
Your code isn't equivalent, the .contains() is more expensive than what you are doing with the raw array. The .contains() walks the entire array every time is called, you don't do this in the raw array based version.
Because int can be much faster than Integer.
Try using Integer[] in the first case or TIntArrayList in the second case for comparison.
If you know the (maximum) number of the elements, try to initialize the Array list with a given size:
ArrayList<Integer> sums = new ArrayList<Integer>(abundants.size() * abundants.size());
With that the ArrayList won't have to be resized, this will increase the speed.

Categories