I have an array that has around 1000 entries, these are split up into 12 entries per year, I'm trying to find the maximum value for each year, to do so I need to read 12 values at a time and find the maximum value of those 12, and then move on to the next 12 values from the array, and so on until it is complete.
Trying to do this I made a temporary array to store the 12 values in, as well as the final array with the max score per year. The code below doesn't work and i'm unsure why, I have spent quite a while researching and attempting this with different solutions, any help will be appreciated :)
//double rain[]= new double [1268]; this is the array declared earlier with data in
double maxRAINyear[]= new double [1200];
double temp [] = new double [12];
int arrayCounter = 0;
int count = 0;
for (int c = 36; c < rain.length; c++) {
temp[count] = rain[c];
if (count == 12){
Arrays.sort(temp);
double max = temp[temp.length - 1];
maxRAINyear[arrayCounter] = max;
arrayCounter++;
count = 0;
}
count++;
}
It's difficult to see what's wrong with your code without knowing what it produces, but in any case this isn't a great way to do this.
I'll assume that you are constrained to the input format of one long array, even though a multidimensional array might make more sense depending on what else it's used for.
// double rain[] = new double[1268]; // input
double maxRAINyear[] = new double[(rain.length+11) / 12];
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < rain.length; i++)
{
if (rain[i] > max) max = rain[i];
if (i % 12 == 0)
{
maxRAINyear[i / 12] = max;
max = Double.NEGATIVE_INFINITY;
}
}
if (rain.length % 12 != 0) maxRAINyear[maxRAINyear.length-1] = max;
This calculates the maximum of each 12 numbers as it goes, rather than storing them separately and sorting them. I've assumed there are a whole number of years stored. If you want to account for a partial year at the end this will need to be modified.
I implemented it without a temporary array, but by just iterating over the array. That should be more efficient.
int amountOfYears = rain.length/12-3;
double maxRAINyear[]= new double [amountOfYears];
for(int i=0;i<amountOfYears;i++){
//Find maximum for these 12 indixes
double max = Double.NEGATIVE_INFINITY;
for(int j=12*i+36;j<12*(i+1)+36;j++){ //use 12*i as an offset, that way, you don't need a temp array
if(rain[j] > max)
max = rain[j];
}
//store maximum
maxRAINyear[i] = max;
}
If you also need to find the partial year, use this
int amountOfYears = Math.ceil(rain.length/12f)-3;
double maxRAINyear[]= new double [amountOfYears];
for(int i=0;i<amountOfYears;i++){
//Find maximum for these 12 indixes
double max = Double.NEGATIVE_INFINITY;
int start = 12*i+36;
int end = Math.min(rain.length,12*(i+1)+36);
for(int j=start;j<end;j++){ //use 12*i as an offset, that way, you don't need a temp array
if(rain[j] > max)
max = rain[j];
}
//store maximum
maxRAINyear[i] = max;
}
When count is 11, you are incrementing it to 12 and going into the next round of the loop. Now temp[count] = rain[c]; will attempt to store a value into index 12 of temp, but there are only 12 entries with indices 0 through 11. So I suspect you are getting an ArrayIndexOutOfBoundsException.
I believe you should move count++ before the if statement. This way a count of 12 will be reset to 0 before it creates any havoc.
This solution have the advantage to work if the array length is not a multiple of the range without doing to many check.
public static double[] read(double[] array, int range) {
double[] result = new double[array.length / range + (array.length % range > 0 ? 1 : 0 )]; //Just add one cell if the length is not a multiple of the range
double max = array[0];
int i = 1;
while (i < array.length) {
if (i % range == 0) { //Next range
result[i / range - 1] = max; //Save last
max = array[i]; //Get current
} else if (array[i] > max) {
max = array[i];
}
++i;
}
result[result.length - 1] = max; //for the last range
return result;
}
Related
I am doing some exercises on codingbat because I have been struggling with arrays. The question was:
"Return the "centered" average of an array of ints, which we'll say is the mean average of the values, except ignoring the largest and smallest values in the array. If there are multiple copies of the smallest value, ignore just one copy, and likewise for the largest value. Use int division to produce the final average. You may assume that the array is length 3 or more."
I was able to code the solution correctly except for 1 part.
The correct code is:
public int centeredAverage(int[] nums) {
int max = nums[0];
int min = nums[0];
int add = nums[0];
for(int i = 1; i < nums.length; i++){
add += nums[i];
if(nums[i] > max){
max = nums[i];
}
else if(nums[i] < min){
min = nums[i];
}
}
return (add - max - min) / (nums.length - 2);
}
My question is why are we starting at int i = 1 rather than 0? If you start at 1 aren't you skipping over a cell?
The initialization:
int max = nums[0];
int min = nums[0];
int add = nums[0];
handles the case when i = 0 for you.
As you are setting max, min and add from zero index of array.By doing this u are finding min and max from a single loop iteration(i.e.. by compairing this values from the other elements of array). If u havn't done this then u have to use some other logic to find min and max of array like O(n)^2 soln.
The purpose of this method is to iterate through a 2D array of integers called grid[][], and translate the integers based on the maximum and minimum values into a smaller range between 100 and 250 (the original minimum value becomes 100, the original maximum value becomes 250, and everything in between is calculated respectively). When this method is called, division by zero ArithmeticException occurs.
Clearly I'm making some logic mistakes here... I just don't see the fix. Can anyone help?
public int greenValues(int arrayVal) {
int max = 0;
int min = 0;
int colorValue = 0;
int temp;
for (int i = 0; i < grid.length; i++) { // finds maximum and minimum numbers in file
for (int j = 0; j < grid.length; j++) {
if (max < grid[i][j]) {
max = grid[i][j];
}
if (min > grid[i][j]) {
min = grid[i][j];
}
}
}
int arrayRange = (max-min); // arrayVal, arrayRange, and max and min are 0
temp = (((arrayVal-min) * COLOR_RANGE) / arrayRange) + 100; // map values to range of 100 - 250
colorValue = temp;
return colorValue;
}
This line is culprint for producing ArithmaticExcpetion.
temp = (((arrayVal-min) * COLOR_RANGE) / arrayRange) + 100;
your calculating arrayRange dynamically as you don't know when that value will be 0. so you can wrap this line with try catch block to do some exception handling.
Solution by Dilip is perfect. Or you can also add a conditional statement which lets it pass only when arrayRange is not 0 & execute something else if it is 0. But it'll increase overhead by executing the conditional statement every time arrayRange is calculated.
I have an array which I would like to find the highest value for, but this value might be repeated.
For example, consider this array of integers:
{10, 2, 6, 25, 40, 58, 60, 60}.
//Here the value 60 is repeated
Here, I would like the output to show that there are two highest values in this array. Like in upper example it have to be show that 60 is highest value among all values in array and that value is 2 time available in array. And i do not want like to count how many numbers but like addition of that two highest numbers. I have search programs but i could not find any relevant solution for this.
class Cal
{
void CalculateThis()
{
int[] myArray = new int[] {20,10,5,40,20,41,41,2,6,7,3,4,5,6,23,34,7,8,9,2};
int max = Integer.MIN_VALUE;
int sum=0;
for(int i = 0; i < myArray.length; i++)
{
if(myArray[i] > max)
{
max = myArray[i]*3;
sum = sum + max;
}
}
System.out.println(sum);
}
}
class program1
{
public static void main(String args[])
{
Cal obj = new Cal();
obj.CalculateThis();
}
}
int max = ar[0];
int maxSum = 0;
for (int i=1; i< ar.length; i++)
{
if(ar[i] > max)
max = ar[i];
else
if(ar[i] == max)
maxSum+=max;
}
int[] myArray = { 10, 2, 6, 25, 40, 58, 60, 60 };
int max = Integer.MIN_VALUE;
int maxCount = 0;
for (int x : myArray) {
if (x > max) {
max = x;
maxCount = 1;
} else if (x == max) {
maxCount++;
}
}
int maxSum = max * maxCount;
System.out.println("Max value : " + max);
System.out.println("Max Count : " + maxCount);
System.out.println("Max Sum : " + maxSum);
output :
Max value : 60
Max Count : 2
Max Sum : 120
There are various approaches you could take here:
Sort the array using Arrays.sort, then work from the end until you saw a different value... letting you work out the value and the count, which you could then multiply together. This is relatively inefficient, as you don't really need to sort.
Write two methods, one of which returned the maximum value and one of which returned the count of a specific value. Find the maximum first, then the count of that, then multiply together. This requires two passes, but is clean in terms of building the final result from separate and reusable operations.
Write a method to keep track of the max and the sum at the same time, resetting both if you see a higher value. This will probably be the most efficient, but wouldn't be reusable for other requirements. (You could equivalently keep track of a count as you went, and multiply the max by count at the end instead.)
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.
Im struggling how to find the maximum amount of dollars that you can achieve with a specified limit on the number of transactions using Dynamic Programming
This not an elegant solution but it will work for this particular problem (I'm guessing we have the same professor).
The logic is that for each V[n][c] we want to find the highest value possible for each unit of currency, and in order to do this we must calculate the maximum value out of 6 vales.
There are 6 values because there are 3 currencies, and each of those currencies has two possible ways that it can be converted into the target currency.
In this case since there are only 2 exchanges I simply do two statements rather than another loop. This is represented by the 0 in the array: rates[0][i][c]
I hope this helps!
for (int n = 1; n <= numberOfTransactions; n++) {
for (int c = 0; c < numberOfcurrencies; c++) {
double max = Double.NEGATIVE_INFINITY;
double temp;
for (int i = 0; i < numberOfcurrencies;i++) {
temp = rates[0][i][c]*V[n-1][i];
if (temp > max)
max = temp;
temp = rates[1][i][c]*V[n-1][i];
if (temp > max)
max = temp;
}
V[n][c] = max;
}
}