How to find the longest sequence of consecutive natural successors? - java

Two consecutive integers are natural successors if the second is the successor of the first in the sequence of natural numbers (1 and 2 are natural successors). Write a program that reads a number N followed by N integers, and then prints the length of the longest sequence of consecutive natural successors.
import java.util.Scanner;
public class objects {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int nmbr[] = new int[x];
for(int f=0;f<nmbr.length;f++)
nmbr[f]=scan.nextInt();
int counter = 0;
int max = 0;
for (int i = 0; i < nmbr.length - 1; i++) {
if (nmbr[i] == (nmbr[i + 1]-1))
counter++;
else
counter = 0;
if (counter > max)
max = (counter+1);
}
System.out.println(max);
}
}
Why is my code still printing the counter without adding one? I am not finding the mistake
sample run:
7 2 3 5 6 7 9 10
2
it is printing 2 instead of 3.

When you see the first number out of sequence, you should reset counter to 1, not 0 - as it's the start of a sequence with length at least 1. You then need to also change the code which changes max:
if (counter > max) {
counter = max;
}
After all, you just want max to be the maximum value of counter.
(I would strongly recommend using braces for every if statement, by the way - it's easier to avoid mistakes that way.)

import java.util.Scanner;
public class objects {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int nmbr[] = new int[x];
for(int f=0;f<nmbr.length;f++) {
nmbr[f]=scan.nextInt();
}
int counter = 0;
int max = 0;
for (int i = 0; i < nmbr.length - 1; i++) {
if (nmbr[i] == (nmbr[i + 1]-1)) {
counter++;
} else {
if (counter > max)
max = (counter+1);
counter = 0;
}
}
System.out.println(max);
}
}
Just a minor error in your logic there, you were updating max every single time the counter was greater than max, so the next time if the sequence comes to an end, it actually fails to register as the longest sequence. Just reorder it as I have done and it works.

Start your conter from 1. because if you start from 0 then it means you are not counting the 1st value.
else
counter = 1;
And Change the dont increment your counter when assigning to max.
max =counter;

Your maximum condition is incorrect:
if (counter > max)
max = (counter+1);
You compare max with counter and assign counter+1. This way when max is equal to 2 it can't be updated with 2+1.
Probably you should use:
if (counter + 1 > max)
max = (counter+1);
P.S.: Your question doesn't show research effort. You could use debug output to understand what is going on with your program. Simplistic example:
for (int i = 0; i < nmbr.length - 1; i++) {
if (nmbr[i] == (nmbr[i + 1]-1))
counter++;
else
counter = 0;
System.out.println("Current value: "+counter);
if (counter > max) {
max = (counter+1);
System.out.println("New max value: "+max);
}
}

This was an easy one and already pointed out in previous answers you are wrongly setting the value of counter in your code.
Run your code through a debugger to keep a track of variable values of what you are expecting from your program versus what you are actually getting.
Stepping through each line of code can help you understand your mistakes better.

you don't take into account the first number, in this case 5
when i == 2 its the start of the sequence, however, nmbr[1] is 3 therfore counter will stil be 0
start the counter to be 1 (this is logic, since the smallest sequence is 1)
you need to change the if to be:
import java.util.Scanner;
public class objects {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int nmbr[] = new int[x];
for(int f=0;f<nmbr.length;f++)
nmbr[f]=scan.nextInt();
int counter = 1;
int max = 1;
for (int i = 0; i < nmbr.length - 1; i++) {
if (nmbr[i] == (nmbr[i + 1]-1))
counter++;
else
counter = 1;
if (counter > max)
max = counter;
}
System.out.println(max);
}
}

Related

Inconsistent results with random rolls and some math

I'm working on making a program to roll 4 6 sided dice and do some simple math and logic with them. I was running a very rough draft of the program and started to notice that the number of rolls would be inconsistent. In particular I would sometimes wont get the smallest value or get two
If looked around for a solution online to no avail. I even copied the code from other examples on how to find the smallest value
public class test {
private static int dice(int s) {
int num = 0;
Random random = new Random();
num = random.nextInt(s);
num = num + 1;
return num;
}
public static void main(String[] args) {
List<Integer> rolls = new ArrayList<Integer>();
for (int i = 0; i != 4; i++) {
rolls.add(dice(6));
}
for (Integer roll : rolls) {
System.out.println(roll);
}
int min = rolls.get(0);
int index = 0;
for (int x = 0; x < rolls.size(); x++) {
if (rolls.get(x) < min) {
min = rolls.get(x);
index = x;
System.out.println("Smallest: " + min);
}
}
int sum = 0;
for (int x : rolls) {
sum += x;
}
System.out.println("Sum:" + sum);
}
}
This should generate 4 rolls of 6 sided dice. Then it should find the smallest value print that, then calculate the sum and print it
Check out this bit of code:
int min = rolls.get(0);
int index = 0;
for(int x = 0; x<rolls.size(); x++){
if(rolls.get(x) < min){
min=rolls.get(x);
index = x;
System.out.println("Smallest: " + min);
}
}
What happens if rolls.get(0); is your minimum roll? In that case, if(rolls.get(x) < min) will always be false, and you'll never print "Smallest...".
Also note that every time you find a roll that is smaller than the last one you looked at, you print out "Smallest..." again, so if you have multiple dice in descending size, you'll print that line out multiple times.
Set your initial min value to 7, so you're guaranteed to have a min value that is smaller than the initial state. And then, instead of printing inside your loop, save the min and print "Smallest..." once the loop is finished:
// Be aware that this code doesn't work correctly if your List is empty.
int min = 7; // You could also set this to rolls.get(0) and start your loop at 1
for (int x = 0; x < rolls.size(); x++) {
if (rolls.get(x) < min) {
min = rolls.get(x);
}
}
System.out.println("Smallest: " + min);
(I also removed index, because it's not being used anywhere in your code).
If you wanted to be a bit more modern with this (and also more robust), you could also do:
rolls.stream()
.min(Integer::compareTo)
.ifPresent(min -> System.out.println("Smallest: " + min));
That will handle the case of rolls being empty by just not printing anything.

Java program calculates average of variable array, input from command line, displays results

Below is what I have so far. The instructions are to create a simple java program that calculates the avg of a variable quantity of ints. Args array for main, no Scanner object, find and display highest and lowest value. Static method that takes user input as argument & returns values. Should display welcome message at launch.
So I think the start of my code is correct! It compiles for me. But I'm not sure how to get user input w/o scanner. I assume I need to use an array in the static method to translate the input into an argument. Which at execution would be java CalculateAverage 1, 2, 5, 9, 20?
And then would I call MATH? So I can display all the values of min max & avg? Am I on the right track..? The questions are specific in the code. Sorry, first time posting here!
public class CalculateAverage {
public static void main(String[] args) {
System.out.print("Hello welcome to the Average Calculator");
int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
//do i just keep going and adding letters til j?
//or is there an easier way to do this..?
minArray(array);
maxArray(array);
sumArray(array);
avgArray(array);
}
public static double maxArray(double[] array){
double max = Double.NEGATIVE_INFINITY;
//tbh i saw this on a tutorial, idk if NEGATIVE_INFINITY would
//work for me?
for (int i = 0; i < n; i++)
if (array[i] > max) max = array[i];
System.out.println("The maximum of your array is:" + max);
}
public static double avgArray(double[] array){
double sum = 0.0;
for(int i = 0; i < n; i++)
sum += array[i];
double avg = sum / n;
System.out.println("The average value of your array is: " + avg);
} //then i would make another static for the min but probably before max
}
From the command line, you want to execute
javac CalculateAverage.java
to have Java compile the class and prepare to run it. Then you can execute the code with
java CalculateAverage arg0 arg1 arg2 ...
Now, in your main( string[] args ) method, I see you're creating an array with 11 elements. This is not necessary, and it is not ideal - what if the user gives more than 11 arguments when they're running the program? The better way to do this is:
int[] array = new int[ args.length ]()
This creates a new array of ints, of the same length as the array args - every array has that property length that states how many elements the array has. Now, we haven't actually put anything in array yet, but we know that it has space for the same number of arguments as the program gave. Now, to initialize each element:
for(int i = 0; i < args.length; i++) {
array[i] = Integer.parseInt(args[i])
}
A for loop creates a variable i (this is the int i = 0 part), initialized to 0, and then executes the code inside the curly brackets. After it's done, it increases the value of i by one (this is the i++ part), and runs the code inside the curly brackets again, continuously, until the condition i < args.length is false. Altogether, this iterates through every element of args and initializes the corresponding element of array.
Now, you could use the Math module to do the calculations for you, but you're almost there in doing it yourself. Here's a slight touch-up to maxArray, for example:
public static int maxarray(int[] array) {
int max = array[0]
for (int i = 1; i < array.length; i++) {
if (array[i] > max) max = array[i];
}
}
System.out.println("The maximum of your array is:" + max);
}
I'm using int here because the inputs were ints. In general you should probably make sure that everything is the same type of variable; either make all the numbers ints or make them all doubles, but don't try to go back and forth between them.
You don't actually need negative infinity for anything; you can just start with the first number in your array, call that the maximum, and then for every number afterwards, replace the maximum if it's larger. We use the for loop in the same way here, to iterate over the entire array.
Similarly, you're doing avgArray(double[] array) correctly already - except that I don't know where you got the variable n from (you should be using array.length again).
Overall, I recommend looking back over your notes for this class so far, and carefully make sure you know what everything means and how it applies to this example. Review what you've been taught about how Arrays work; and about the differences between ints and doubles.
This is what I would do. Hopefully the code is simple and self-explanatory but let me know if any questions:
public static void main(String[] args) {
System.out.println("Hello welcome to the Average Calculator");
int numArgs = args.length; //Since args is an array we can get the number of elements with .length
int min = Integer.MAX_VALUE; //The maximum possible value an int can be
int max = Integer.MIN_VALUE; //The minimum possible value an int can be
double total = 0;
for(int i = 0; i < numArgs; i++) {
int nextI = Integer.parseInt(args[i]);
total += nextI;
if(nextI < min) {
min = nextI;
}
if(nextI > max) {
max = nextI;
}
}
System.out.println("The average is: " + total/numArgs);
System.out.println("The min is: " + min);
System.out.println("The max is: " + max);
}
Then, you would run the code like this:
java CalculateAverages 1 2 3 4 5 6 7 8 9
Hello welcome to the Average Calculator
The average is: 5.0
The min is: 1
The max is: 9
Edit:
The instructions said "To find these value, make static methods that
take the user input as arguments & returns the value"
public static void main(String[] args) {
int numArgs = args.length;
int[] userIntInputs = new int[numArgs];
for(int i = 0; i < numArgs; i++) {
userIntInputs[i] = Integer.parseInt(args[i]);
}
System.out.println("The average is: " + getInputAverage(userIntInputs));
System.out.println("The min is: " + getInputMin(userIntInputs));
System.out.println("The max is: " + getInputMax(userIntInputs));
}
private static int getInputMax(int[] userIntInputs) {
int max = Integer.MIN_VALUE;
for(int i = 0; i < userIntInputs.length; i++) {
if(userIntInputs[i] > max) {
max = userIntInputs[i];
}
}
return max;
}
private static int getInputMin(int[] userIntInputs) {
int min = Integer.MAX_VALUE;
for(int i = 0; i < userIntInputs.length; i++) {
if(userIntInputs[i] < min) {
min = userIntInputs[i];
}
}
return min;
}
private static double getInputAverage(int[] userIntInputs) {
double total = 0;
for(int i = 0; i < userIntInputs.length; i++) {
total += userIntInputs[i];
}
return total/userIntInputs.length;
}
One Method Alternative
Idk if she means to make a method for each value or one method!
Yeah teachers can be confusing all right. Here's a one method approach...
public static void main(String[] args) {
int numArgs = args.length;
int[] userIntInputs = new int[numArgs];
for(int i = 0; i < numArgs; i++) {
userIntInputs[i] = Integer.parseInt(args[i]);
}
Object[] inputMetrics = getInputMetrics(userIntInputs);
System.out.println("The average is: " + inputMetrics[0]);
System.out.println("The min is: " + inputMetrics[1]);
System.out.println("The max is: " + inputMetrics[2]);
}
private static Object[] getInputMetrics(int[] userIntInputs) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
double total = 0;
for(int i = 0; i < userIntInputs.length; i++) {
int nextI = userIntInputs[i];
total += nextI;
if(nextI < min) {
min = nextI;
}
if(nextI > max) {
max = nextI;
}
}
Object[] metrics = {total/userIntInputs.length, min, max};
return metrics;
}
Simplicity is IMHO the best way. This does the whole thing:
DoubleSummaryStatistics stats = Arrays.stream(args)
.collect(Collectors.summarizingDouble(Double::parseDouble));
System.out.println("The minimum of your array is: "+ stats.getMin());
System.out.println("The maximum of your array is: "+ stats.getMax());
System.out.println("The sum of your array is: "+ stats.getSum());
System.out.println("The average of your array is: "+ stats.getAverage());
When there's a built-in library to handle something, use it.

Find Maximum Positive Index

You are given an array A. We define a term Positive difference index as the count of elements between the two indexes i and j (both inclusive) such that i<j and A[i]<A[j].
Now for the given array, you have to find the maximum positive difference index. It is assured that the test case will be valid such that there exists an answer.
Input format
First line : T i.e Number of test cases.
For each test case :
First line : N
Second line : N space separated integers denoting the element of the array.
Output format
Print the answer to each test case in a separate line and it is given that answer always exists.
Sample Input
1
6
5 3 2 1 1 4
Sample Output
5
Explanation
let i=2 and j=6 then A[i]<A[j] and total elements between them is 5 so the maximum answer that can be achieved is 5.
I had tried to find maximun number from an array and minimum number from array such that A[i]<A[j]. With sample input it worked but for when I submitted the question on hackerearth it displayed none test cases were passed. Can anyone please me help to understand the question and program?
Below program I have written
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int totalTest = Integer.parseInt(line);
for(int i=0;i<totalTest;i++) {
line = br.readLine();
int totalElements = Integer.parseInt(line);
line = br.readLine();
String strArr[] = line.split(" ");
int elements[] = new int[strArr.length];
for(int j=0;j<strArr.length;j++) {
elements[j] = Integer.parseInt(strArr[j]);
}
System.out.println(findMaximumPositiveIndex(elements));
}
}catch(Exception e) {
e.printStackTrace();
}
finally {
if(br!=null)
br.close();
}
}
public static int findMaximumPositiveIndex(int[] arr) {
int max=arr[0];
int maxIndex = 0;
int minIndex=arr[0];
int min=0;
for(int i=0;i<arr.length;i++) {
if( min==0 ) {
min = arr[i];
minIndex=i;
}
if(arr[i] < min) {
min = arr[i];
minIndex = i;
}
if(arr[i] > max) {
max = arr[i];
maxIndex = i;
}
}
return (max - min) + 1;
}
}
The maximum and minimum values from the array, in most cases they won’t help you. So don’t find those. In the example in the question the maximum value is 5 and the minimum is 1. Neither of those two values are involved in calculating the output. Instead the values 3 and 4 are because they are the farthest apart values that fulfil the condition A[i] < A[j]. The output should be 5 because the part of the array 3 2 1 1 4 has length 5. Or “the count of elements between the two indexes i and j (both inclusive)”, as the challenge puts it.
Instead you find the output from the min and max values as (5 – 1) + 1 = 5 (I think; I haven’t studied your code thoroughly). Coincidentally you hit the correct output in this single case. You haven’t done it correctly.
Other examples:
For 2 1 2 1 2 1 the answer is 4 because the part 1 2 1 2 has length 4 and 1 < 2.
For 40 90 10 60 the answer is 4 too because 40 90 10 60 has 4 elements in it and 40 < 60.
I understood that you asked for help understanding the problem, not for solving it, so I am happy to leave that pleasure to yourself.
Thanks for helping to understand the problem statement.
I have modified the code
public static int findMaximumPositiveIndex(int[] arr) {
int min=arr[0],max=arr[0],minIndex=0,maxIndex=0;
int maximumIndex = 0;
for(int i=0;i<arr.length;i++){
min = arr[i];
minIndex=i;
boolean isMaxPresent = false;
for(int j=i;j<arr.length;j++)
{
if(arr[j] > min){
max = arr[j];
maxIndex = j;
isMaxPresent = true;
}
}
if(maximumIndex < ((maxIndex - minIndex) +1) )
maximumIndex = (maxIndex - minIndex) + 1;
}
return maximumIndex;
}
which fulfills all the test cases. Thanks

Moving Average Using User-Input Array

I need to write a program that calculates a moving average by a user inputted array. The first element of the array is the window size, and the input is terminated by a 0. The output values are printed with two digits after the decimal point.
Example input: 3 2 4 7 7 8 11 12 0
Corresponding Output: 4.33 6.00 7.33 8.67 10.33
(4.33 is average of 2,4,7 and 6 is average of 4,7,7 etc.)
Here's my code so far:
package movingaverage;
import java.util.Scanner;
public class MovingAverage {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
avg[0] = sum / 5;
int j = 1;
for (int i = 5; i < arr.length; i++) {
sum = sum + arr[i] - arr[i - 5];
avg[j++] = sum / 5;
}
}
}
I think I have the loop right, but I'm not sure how to get the array to end at 0.
This is a possible solution.
public class Test
{
private static final Scanner SCANNER;
static {
SCANNER = new Scanner(System.in);
}
public static final void main(final String... args) {
final String[] numbers = SCANNER.nextLine().trim().split(" ");
final int consideredElements = Integer.parseInt(numbers[0]);
float sum = 0;
int value = 0;
for (int i = 1; i < numbers.length; i++) {
sum = 0;
for (int k = 0; k < consideredElements; k++) {
value = Integer.parseInt(numbers[i + k]);
if (value == 0) {
return;
}
sum += value;
}
System.out.println(new BigDecimal(sum / consideredElements).setScale(2, RoundingMode.HALF_EVEN));
}
}
}
First, you are using 5 in a couple of places in your program, I see no justification for that. Could it be that your expectation of user input lead you to put 5 where the number you really should use, depends on user input? Maybe you should use the window size instead? I’m guessing a bit here.
Next, as #lppEdd pointed out, you are not reading the numbers from your input — only the window size.
Next, you are declaring your array of size n, which I believe was your window size, not your array size. I believe the real solution to this problem is using better and more explanatory variable names.
Your code does not compile since you have not declared the array avg that you try to store your moving average into.
Fifth, when you want your average as a double, you need to convert to double before dividing (this is a classic pitfall that has already generated many questions on Stack Overflow).
I hope this gets you a couple of steps further.

in Java, design linear algorithm that finds contiguous subsequence with highest sum

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.

Categories

Resources