I am new to the site, and new to programming in general, so please be gentle. I'm doing an assignment and I've built everything it needs, but I'm having problems with one particular part.
So the code below is just the for loop part of the overall program that I'm having trouble with. I created an array to store the user's quarterly input. When I go to determine which quarter had the largest rainfall, the code works no problem.
Where I'm having problems however is when I try to determine the quarter with the least amount. I basically set them both up the same way, but it doesn't work. I'm sure I must have a logic problem somewhere in there, but I've racked my brain trying to figure it out. Any help would be greatly appreciated. I'm sure its something small and stupid that I'm doing.
double largest=0;
for (int k = 0; k < quarterlyArray.length; k++) { // Determines the largest quarterly rainfall.
if ( quarterlyArray[k] >= largest ) {
largest = quarterlyArray[k];
}
}
for (int k = 0; k < quarterlyArray.length; k++) { // Determines in which quarter had largest rainfall.
if (quarterlyArray[k] == largest) {
System.out.println("Quarter " + (k+1) + " saw the most rain this year with " + largest + " inches.");
}
}
double smallest = 0;
for (int p = (quarterlyArray.length-1); p == 0; p--) { // This is not working right now.
if (quarterlyArray[p] < quarterlyArray [quarterlyArray.length-1] || quarterlyArray[p] < smallest) {
quarterlyArray[p] = smallest;
}
}
for (int l = quarterlyArray.length; l == 0; l--) { // Nor this.
if (quarterlyArray[l] == smallest) {
System.out.println("Quarter " + (l+1) + " saw the least rain this year with " + smallest + " inches.");
}
}
A few things that I notice, that are contributing to your problem:
for (int p = (quarterlyArray.length-1); p == 0; p--) {
The p == 0 is the termination expression. Your loop will only iterate while this condition is true. Your loop will not execute because the condition is false on the first iteration.
for (int l = quarterlyArray.length; l == 0; l--) {
Same problem in this loop, too. Look at your condition in your first for loop - k < quarterlyArray.length. When this is false, your loop will terminate.
quarterlyArray[p] = smallest
You are modifying the array rather than your local variable smallest.
You also need to be careful about bounds of the arrays. Your loop sets l to the array length - int l = quarterlyArray.length. If you then try to index into this array using quarterlyArray[l] you would get an ArrayIndexOutOfBoundsException because Java arrays (and most programming languages I would say) are 0-based.
Another thing to point out is how you are calculating both the min and max. Say, for example, that your quarterlyArray contains all negative values. What would largest be? Well, none of the items in the array are greater than 0, so largest would be 0. That would be incorrect because that value is not in the array.
In your first case, it looks like you are starting with an element that you know will always be lower than the elements in the array. This works out fine if you know all the elements will be greater than that. Your double largest = 0 will be changed to the maximum value of the array based on the constraints of the problem you are solving.
A better way to approach this is to start with a known element from the array. If you simply change your largest to be the first/last element from the array, and then go through the rest, you will always come out with the desired result.
double largest = quarterlyArray[0];
for (int k = 1; k < quarterlyArray.length; k++) { // Determines the largest quarterly rainfall.
if ( quarterlyArray[k] >= largest ) {
largest = quarterlyArray[k];
}
}
Notice how all I changed was the initialization of largest, and int k = 1. You can do the same thing for smallest. In this case, I start from the end of the array.
double smallest = quarterlyArray[quarterlyArray.length - 1];
for (int p = quarterlyArray.length - 2; p >= 0; p--) {right now.
if (quarterlyArray[p] < smallest) {
smallest = quarterlyArray[p];
}
}
Another note for after you get through this, is how could do both in 1 for loop?
Start the last loop form quarterlyArray.length-1.Change to
for (int l = quarterlyArray.length-1; l >= 0; l--)
The last element of the array would be at quarterlyArray.length-1 not at quarterlyArray.length
And l == 0(termination expression) should be l >= 0 because when the termination expression evaluates to false, the loop terminates.
Your loop for the smallest is all wrong - you are setting the array values, not finding the smallest.
Do it all in one loop:
double largest=Double.MIN_VALUE;
double smallest = Double.MAX_VALUE;
for (int k = 0; k < quarterlyArray.length; k++) {
if ( quarterlyArray[k] > largest ) {
largest = quarterlyArray[k];
}
if ( quarterlyArray[k] < smallest ) {
smallest = quarterlyArray[k];
}
}
You can also refine this in the manner shown by #mkobit to make it a bit faster:
double largest=quarterlyArray[0];
double smallest = largets;
for (int k = 1; k < quarterlyArray.length; k++) {
if ( quarterlyArray[k] > largest ) {
largest = quarterlyArray[k];
} else if ( quarterlyArray[k] < smallest ) {
smallest = quarterlyArray[k];
}
}
Of course, you should first check to ensure that quarterlyArray has a length greater than zero.
Related
So as part of a task, I was asked to create an array with randomized values within a range, and then to sort it from smallest to biggest (I used a bubble sort), and then to firstly, print the sum of all the elements in the array, then to list them from smallest to biggest.
My issue is that I keep getting the ArrayIndexOutOfBoundsException error, but cannot find where this problem lies.
You can see in the code that I've put in the randomArrays method, a for loop that creates the random values for the array size I declared in the main method, then, underneath the for loop, I've created an if statement that checks to see if an element's value is bigger than the element after it, if it is, it swaps the place of the elements, until they're all sorted into smallest to biggest, and the loop is terminated.
Any help is much appreciated, thank you :)
public class MyArray {
public static void main(String[] args) {
int[] elements = new int[50];
int min = 0;
int max = 50;
randomArrays(elements, max, min);
}
public static void randomArrays(int[] elements, int max, int min) {
int range = max - min; //defines the range of the integers
int temp;
boolean fixed = false;
while (fixed == false) {
fixed = true;
for (int i = 0; i < elements.length; i++) {
elements[i] = min + (int) (Math.random() * range);
while (i < elements.length) {
if (elements[i] > elements[i + 1]) {
//if 8 > 5
temp = elements[i + 1];
//store 5 in temp
elements[i + 1] = elements[i];
//put the 8 in the 5's place
elements[i] = temp;
fixed = false;
}
i++;
}
}
}
}
//System.out.println(elements[i]);
}
My issue is that I keep getting the ArrayIndexOutOfBoundsException
error, but cannot find where this problem lies.
Problem lies in the condition of the for loop. You get ArrayOutOfBounds exception when i=49 and then you try to access i+1 index which doesn't exists.
Change
for (int i = 0; i < elements.length; i++)
to
for (int i = 0; i < elements.length-1; i++)
As you can already see that your code is going out of the arrays limit.
if you look at your code, following is where this is happening
while (i < elements.length) {
Its this while loop part, so if you change it to correctly loop thru the right number of elements, your problem will be resolved..change your while loop code with this one
while (i < elements.length-1) {
I'm fairly new to java so I would like to keep it simple, and I figure I would have to take the first value of the array then compare it to each following value and if the value is larger smaller than the first, replace the value with it, but I don't know how to get index from that.
For an unstructured, unsorted array the best you can do, assuming you are only going to find the minimum value once, is a simple iteration over all elements (O(n) complexity), like so:
public int findMinIdx(int[] numbers) {
if (numbers == null || numbers.length == 0) return -1; // Saves time for empty array
// As pointed out by ZouZou, you can save an iteration by assuming the first index is the smallest
int minVal = numbers[0] // Keeps a running count of the smallest value so far
int minIdx = 0; // Will store the index of minVal
for(int idx=1; idx<numbers.length; idx++) {
if(numbers[idx] < minVal) {
minVal = numbers[idx];
minIdx = idx;
}
}
return minIdx;
}
Also, in the case of a tie for minimum value, this method will return the index of the first case of that value it found. If you want it to be the last case, simply change numbers[idx] < minVal to numbers[idx] <= minVal.
Here is with Java 8
public static int findMinIdx(int[] numbers) {
OptionalInt minimun = IntStream.of(numbers).min();
return IntStream.of(numbers).boxed().collect(toList()).indexOf(minimun.getAsInt());
}
Never cared about run time optimization, was just looking for a solution!, this worked and this would help you too, finding the index of the lowest values in an array.
// array[] -> Received the array in question as an parameter
// index -> stores the index of the lowest value
// in for loop, i is important to complete all the comparison in the function
// When it finds a lower value between the two, it does not change the index
// When it finds a lower value it changes it's index to that index
// If array has same value more than once, it will provide index to that values last occurrence
// Correct me if you find anything not working in this example...
//...
private static int index_of_minimum_value(int[] array) {
int index = 0;
for (int i = 1; i < array.length; i++) {
if ((array[i - 1] < array[i]) && ([index] > array[i - 1])) index = i - 1;
else if (array[index] > array[i]) index = i;
}
return index;
}
I having a really hard time finding a plateau within an array. What I'm looking for is length and location of the longest sequence of equal values where the numbers on both sides are smaller. Now I know there could be two or more valid plateaus with same length ideally I would like to print the plateau with a higher value.
I have created an array[40] and a Random obj. To fill the array, once I have filled it I know I will need a loop to check the indexes. But thats where the confusion comes in. I have tried using a for loop to find the plateau but my results would just increase the value stored within the index.
Any points in the right direction I would greatly appreciate it.
import java.util.Random;
public class Plateau {
public static void main(String[]args)
{
int[] array1 = new int[40];
Random genrator = new Random();
for (int i = 0; i < array1.length; i++)
{
array1[i] = genrator.nextInt(21 - 1);
}
for(int i = 0; i < array1.length; i++)
{
System.out.print(array1[i] + " ");
}
System.out.println("\n");
for (int i = 0; i < array1.length; i++)
{
if (array1[i] < array1[i] + 1)
{
System.out.println(array1[i] + " ");
}
}
}
}
In pseudo-code:
V value=first value
P position=1
L length=0
Scan the values from position Q=2
Compare current value C to V
If C is less than V
if this sequence Q-P is longer than L
save length as L
save P as location R
update V and P to current value
If C is greater than V
update V and P to current value
I don't have a compiler for pseudo-code so it might not be exactly right, but it should be a start.
this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.
I will be creating an array that accepts 10 integers from the user, finds the second largest value, and finally adds all odd numbers. If I use 10-1 as input, it will do everything correctly; the problem arises when the first number entered is an odd number it will ignore it in the summation and I have no idea as to why. Any ideas?
for (int j = 0; j < 10; j++) {
arra[j] = keyboard.nextInt();
if (arra[j] > maxValue) {
secondLargest = maxValue;
maxValue = arra[j];
} else if (arra[j] > secondLargest) {
secondLargest = arra[j];
}
}
System.out.println("The second largest number is: " + secondLargest);
for (int i = 0; i < arra.length; i++) {
if (i % 2 == 0) {
numberOdds++;
}
}
int[] odds = new int[numberOdds];
for (int i = 1; i < arra.length; i++) {
if (arra[i] % 2 == 1) {
odds[count] = arra[i];
count++;
}
}
for (int i = 0; i < odds.length; i++) {
sum = sum + odds[i];
}
System.out.println("The sum of all odd numbers is: " + sum);
[This appears to be homework, so exact code will not be given.]
For good form, consider getting the input array separately -- then call a method to get each computational result you want.
For "second largest" method, you do not appear to be initializing the two values. Make sure you handle the (odd) case in which all values in the array are the same. Perhaps you want to set the max and the second-to-max to the first array value and then loop on the 2nd through the end?
To add all the odd numbers create a method that sets the initial sum to zero and then add a number only if it is odd (n % 2 != 0)