My objective is to remove all negative numbers from an array in Java.
I have written the below code. How do I improve the complexity of code or is there a good algorithm?
public static void main(String[] args) {
int[] array = { 1, -3, 4, -9, 3, 4, 70, -10, 0, 7 };
System.out.println(Arrays.toString(removeNegativeNumbers(array)));
}
public static int[] removeNegativeNumbers(int[] num) {
List<Integer> list = new ArrayList<>();
for (int n : num) {
if (n >= 0) {
list.add(n);
}
}
int[] result = new int[list.size()];
for (int i = 0; i < result.length; i++) {
result[i] = list.get(i).intValue();
}
return result;
}
What about Java 8 streams?
Arrays.stream(num).filter(s -> s >= 0).toArray();
How do I improve the complexity of code or is there a good algorithm?
Here is a linear O(n) algorithm with constant space (neglecting the space we need for output array). When an element is non-negative, copy the element and advance both output array and input array seeker. And when the element is negative, advance only the input array seeker(indx) and avoid copying to output array.
public static int[] removeNegativeNumbers(int[] num) {
int[] output = new int[num.length];
int k = 0;
for(int i = 0; i < num.length; i++) {
if(num[i] >= 0) {
output[k++] = num[i];
}
}
return Arrays.copyOfRange(output, 0, k);
}
Space Efficient Solution
You can make the algorithm in-place by transforming the input array to hold output like insertion sort way to avoid the space overhead of output array.
public static int removeNegativeNumbers(int[] num) {
int k = 0;
for(int i = 0; i < num.length; i++) {
if(num[i] >= 0) {
num[k++] = num[i];
}
}
// Now input array is holding the output data
// Return the length of output array
return k;
}
// Usage: int newLen = removeNegativeNumbers(array);
This is called two pointers technique, very simple yet useful to solve many classical puzzles like Array de-duplication, merging two sorted arrays, intersection of two sorted arrays etc.
I don't think we can get better in terms of efficiency than #kaidul-islam answer (and #user6904265 in terms of conciseness).
I'm just adding a solution that should have some value in a very specific scenario, where negatives rarely appear and array is very large.
Basic idea is to defer the actual copy until a negative value is found and then copy with System.arraycopy. In case no negative is found, the source array would be returned.
import java.util.*;
public class NotNegativeTest {
public static void main(String[] args) {
int[] array = { 1, -3, 4, -9, 3, 4, 70, -10, 0, 7 };
System.out.println(Arrays.toString(removeNegativeNumbers(array)));
}
public static int[] removeNegativeNumbers(int[] num) {
int[] output = new int[num.length];
int k = 0;
int i = 0;
int last=-1;
int howmany=0;
while(i < num.length) {
if(num[i] < 0) {
howmany=i-last-1;
switch(howmany) {
case 0: break;
case 1:
output[k]=num[last+1];
k++;
break;
default:
System.arraycopy(num, last+1, output, k, howmany);
k+=howmany;
}
last=i;
}
i++;
}
if (last>=0) {
if(last!=i-1) {
howmany=i-last-1;
System.arraycopy(num, last+1, output, k, howmany);
k+=howmany;
}
} else {
return num;
}
return Arrays.copyOfRange(output, 0, k);
}
}
I've found the time to write a JMH microbenchmark.
I've used used these configurations:
Options opts = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.mode(Mode.AverageTime)
.warmupIterations(1)
.warmupTime(TimeValue.seconds(5))
.measurementIterations(10)
.measurementTime(TimeValue.seconds(5))
.jvmArgs("-server")
.forks(1)
.build();
new Runner(opts).run();
(disclaimer: my first JMH test, so if someone has some suggestions, I'll be glad to change it and update the results)
And here are the results:
# Run complete. Total time: 00:02:54
Benchmark Mode Cnt Score Error Units
MyBenchmark.testMethodUser6904265 avgt 10 0,201 ± 0,040 s/op
MyBenchmark.testMethodInsac avgt 10 0,093 ± 0,022 s/op
MyBenchmark.testMethodKaidul avgt 10 0,124 ± 0,029 s/op
Now, before cheering me, please take a look to how biased the test was:
int[] array = new int[10000000];
array[0]=-5;
array[10000]=-3;
array[40000]=-3;
array[8000000]=-3;
int[] answer=NotNegativeTest.removeNegativeNumbers(array);
So here the thing to notice it is not that my method won (the test was written for my method to win :-) but how close the generic kaidul-islam method was to mine even in this extreme scenario.
UPDATED: here is the link to the jmh benchmark I wrote so you can verify more realistic scenario (if someone finds issues with how I setup the test, please let me know). There is a depenendency on Trove for a test I've done on another answer.
This will do it in-place with a single iteration:
Hold 2 indexes: src and dst on the original array. both are initialized to 0.
when a number is positive, copy it from num[src] to num[dst] and advance both indexes
when a number is negative, just advance src.
return the original array with dst as its new size.
public static int removeNegativeNumbers(int[] num) {
int dst=0;
for (int src=0 ; src<num.length ; ++src)
if (num[src]>=0)
num[dst++] = num[src];
return dst;
}
Follow the below code (Java 8)
int test[] = new int[] { 15, -40, -35, 45, -15 };
// here we can take the test array in to stream and filter with condition (>=0).
int[] positives = Arrays.stream(test).filter(x -> x >= 0).toArray();
System.out.println("Here is the positive array elements");
for (int i : positives) {
System.out.print(i + "\t");
}
Since you will necessarily need to look at each individual element to determine if it is less than 0, the runtime must be at least O(n). Since the space needed to store the input is O(n), the space is at least O(n). Your solution runs in O(n) time with O(n) complexity, therefore no solution can have better space or runtime complexity than your solution
We can, however, get better results if we assume the array is sorted. Then, we do a binary search for 0. If we have a way to return the sub-array with constant time (e.g. pointer magic in C, or by simply returning the start index to be read), then the algorithm would have O(log n) time.
Use iterator
Iterator<Integer> itr = objArray.iterator();
while(itr.hasNext()) {
Integer next = itr.next();
if(next < 0) {
itr.remove();
}
}
public static int[] removeNegativeNumbers(int[] num) {
List<Integer> list = new ArrayList<>();
for (int n : num) {
if (n >= 0) {
list.add(n);
}
}
return list.toArray(new int[list.size()]);
}
Related
Write a function:
class Solution{
public int solution(int[] A);
}
that, given an array A of N integers, returns the smallest positive integer(greater than 0)
that does not occur in A.
For example, given A = [1,3,6,4,1,2], the function should return 5.
Given A = [1,2,3], the function should return 4.
Given A = [-1, -3], the function should return 1.
Write an efficient algorithm for the following assumptions.
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [-1,000,000..1,000,000].
I wrote the following algorithm in Java:
public class TestCodility {
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
//int a[] = {1,2,3};
//int b[] = {-1,-3};
int element = 0;
//checks if the array "a" was traversed until the last position
int countArrayLenght = 0;
loopExtern:
for(int i = 0; i < 1_000_000; i++){
element = i + 1;
countArrayLenght = 0;
loopIntern:
for(int j = 0; j < a.length; j++){
if(element == a[j]){
break loopIntern;
}
countArrayLenght++;
}
if(countArrayLenght == a.length && element > 0){
System.out.println("Smallest possible " + element);
break loopExtern;
}
}
}
}
It does the job but I am pretty sure that it is not efficient. So my question is, how to improve this algorithm so that it becomes efficient?
You should get a grasp on Big O, and runtime complexities.
Its a universal construct for better understanding the implementation of efficiency in code.
Check this website out, it shows the graph for runtime complexities in terms of Big O which can aid you in your search for more efficient programming.
http://bigocheatsheet.com/
However, long story short...
The least amount of operations and memory consumed by an arbitrary program is the most efficient way to achieve something you set out to do with your code.
You can make something more efficient by reducing redundancy in your algorithms and getting rid of any operation that does not need to occur to achieve what you are trying to do
Point is to sort your array and then iterate over it. With sorted array you can simply skip all negative numbers and then find minimal posible element that you need.
Here more general solution for your task:
import java.util.Arrays;
public class Main {
public static int solution(int[] A) {
int result = 1;
Arrays.sort(A);
for(int a: A) {
if(a > 0) {
if(result == a) {
result++;
} else if (result < a){
return result;
}
}
}
return result;
}
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
int b[] = {1,2,3};
int c[] = {-1,-3};
System.out.println("a) Smallest possible " + solution(a)); //prints 5
System.out.println("b) Smallest possible " + solution(b)); //prints 4
System.out.println("c) Smallest possible " + solution(c)); //prints 1
}
}
Complexity of that algorithm should be O(n*log(n))
The main idea is the same as Denis.
First sort, then process but using java8 feature.
There are few methods that may increase timings.(not very sure how efficient java 8 process them:filter,distinct and even take-while ... in the worst case you have here something similar with 3 full loops. One additional loop is for transforming array into stream). Overall you should get the same run-time complexity.
One advantage could be on verbosity, but also need some additional knowledge compared with Denis solution.
import java.util.function.Supplier;
import java.util.stream.IntStream;
public class AMin
{
public static void main(String args[])
{
int a[] = {-2,-3,1,2,3,-7,5,6};
int[] i = {1} ;
// get next integer starting from 1
Supplier<Integer> supplier = () -> i[0]++;
//1. transform array into specialized int-stream
//2. keep only positive numbers : filter
//3. keep no duplicates : distinct
//4. sort by natural order (ascending)
//5. get the maximum stream based on criteria(predicate) : longest consecutive numbers starting from 1
//6. get the number of elements from the longest "sub-stream" : count
long count = IntStream.of(a).filter(t->t>0).distinct().sorted().takeWhile(t->t== supplier.get()).count();
count = (count==0) ? 1 : ++count;
//print 4
System.out.println(count);
}
}
There are many solutions with O(n) space complexity and O(n) type complexity. You can convert array to;
set: array to set and for loop (1...N) check contains number or not. If not return number.
hashmap: array to map and for loop (1...N) check contains number or not. If not return number.
count array: convert given array to positive array count array like if arr[i] == 5, countArr[5]++, if arr[i] == 1, countArr[1]++ then check each item in countArr with for loop (1...N) whether greate than 1 or not. If not return it.
For now, looking more effective algoritm like #Ricola mentioned. Java solution with O(n) time complexity and O(1) space complexity:
static void swap(final int arr[], final int i,final int j){
final int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static boolean isIndexInSafeArea(final int arr[], final int i){
return arr[i] > 0 && arr[i] - 1 < arr.length && arr[i] != i + 1 ;
}
static int solution(final int arr[]){
for (int i = 0; i < arr.length; i++) {
while (isIndexInSafeArea(arr,i) && arr[i] != arr[arr[i] - 1]) {
swap(arr, i, arr[i] - 1);
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] != i + 1) {
return i+1;
}
}
return arr.length + 1;
}
I am attempting to sort an array of integers such that all even numbers precede odd numbers, without using any external libraries.
You may recognize this from: http://codingbat.com/prob/p105771
" Return an array that contains the exact same numbers as the given array, but rearranged so that all the even numbers come before all the odd numbers. Other than that, the numbers can be in any order. You may modify and return the given array, or make a new array. "
I have code that accomplishes this goal:
public int[] evenOdd(int[] nums) {
int c=0;
int c2=0;
int [] nums2=new int[nums.length];
for(int i=0;i<nums.length;i++)
{
if(nums[i]%2==0)
{
nums2[c]=nums[i];
c++;
}
else
{
nums2[nums.length-c2-1]=nums[i];
c2++;
}
}
return nums2;
}
I have also approached the problem by calling array.sort() and then inserting the numbers by index, incrementing by two, then inserting the remainder. This also works.
So, to make a long post short-is there a more elegant way to accomplish this goal in future?
Thanks!
Just a follow-up to my comment. Here is how you can do it in O(n) without extra-space:
public class Main {
public static void main(String[] args) {
evenOdd(new int[]{1, 2, 3, 4, 5, 6, 7});
evenOdd(new int[]{2, 3, 4, 5, 6, 7});
evenOdd(new int[]{1, 1, 1, 1, 1});
evenOdd(new int[]{2, 2, 2, 2});
}
public static void evenOdd(int[] a) {
int firstOdd = 0;
for (int i = 0; i < a.length; ++i) {
if (a[i] % 2 == 0) {
int t = a[firstOdd];
a[firstOdd] = a[i];
a[i] = t;
firstOdd++;
// } else {
// else is redundant, just leave odd in-place
}
}
System.out.println(Arrays.toString(a));
}
}
Create a wrapper object that contains an int, call it SortingWrapper. This object should implement Comparable, such that its natural sort order is based on the sort order of value%2. Then just sort the array with Arrays.sort(). Based on the compareTo() implementation, the evens will naturally (ie, according to their natural sort order) bubble one way, all the odds will bubble the other.
Alternatively, you could just uses Integers as your wrapper and pass a Comparator that does the same thing to Arrays.sort().
edit- here is the general idea. You might have to play around with the sort order, but I think this pretty much works. I suspect that this array will count as "mostly sorted" which would make performance tend more towards O(n) than log(n), based upon the javadoc for Arrays.sort().
public void sortOddsAndEvents(Integer[] input)
{
Arrays.sort(input, new Comparator<Integer>()
{
#Override
public int compare(Integer arg0, Integer arg1)
{
if (arg0.equals(arg1)) return 0;
else return Integer.compare(arg0.intValue()%2, arg1.intValue()%2);
}
});
}
public int[] evenOdd(int[] nums) {
int evenCounter = -1, oddCounter = nums.length;
int[] ordered = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
int current = (nums[i] % 2 == 0) ? ++evenCounter : --oddCounter;
ordered[current] = nums[i];
}
return ordered;
}
Background: Very new at Java, have little understanding. Would prefer a "point in the right direction" with explanation, if possible, than a copy/paste answer without explanation. If I want to stop being a novice, I need to learn! :)
Anyway, my goal is, as simply as possible, to be given 2 arrays numberList and winningNumbers, compare them, and return the percentage that numberList matches winningNumbers. Both array lengths will always be 10.
I have no idea where to start. I have been googling and going at this for 2 hours. My idea is to write a for loop that compares each individually integer in a string to one in the other, but I am not sure how to do that, or if there is a simpler method. I have little knowledge of arrays, and the more I google the more confused I become.
So far the only thing I have is
public double getPercentThatMatch(int[] winningNumbers) {}
numberList is preset.
one way you could approach it is to:
1) convert both lists to sets.
2) subtract one from the other. ie if 4 are the same, the resulting set will have the 6 values not the same
3) 10 - (size of resulting set) * 100 = %
Here's a runnable example of how you would compare the two arrays of ints to get a percent match.
public class LotteryTicket {
int[] numberList;
LotteryTicket(int... numbers) {
numberList = numbers;
}
public int getPercentThatMatch(int[] winningNumbers) {
Arrays.sort(numberList);
Arrays.sort(winningNumbers);
int i = 0, n = 0, match = 0;
while (i < numberList.length && n < winningNumbers.length) {
if (numberList[i] < winningNumbers[n]) {
i++;
} else if (numberList[i] > winningNumbers[n]) {
n++;
} else {
match++;
i++;
n++;
}
}
return match * 100 / winningNumbers.length;
}
public static void main(String[] args)
{
int[] winningNumbers = { 12, 10, 4, 3, 2, 5, 6, 7, 9, 1 };
LotteryTicket ticket = new LotteryTicket(5, 2, 6, 7, 8, 4, 3, 1, 9, 0);
int percentMatching = ticket.getPercentThatMatch(winningNumbers);
System.out.println(percentMatching + "%");
}
}
Output:
80%
Since you wanted to be pointed in the right direction, rather than havving proper code, and assuming you want to use arrays to solve the problem, try to put something like this in your method:
(loop through arrayA){
(loop through arrayB){
if (current arrayA number is equal to current arrayB number){
then increase match counter by one, since this exists.
also break out of current arrayB loop. (Check next arrayA now.)
}
}
}
When done: return 100*matchCount/totalCount, as a double
So for every index in one array, you check against every other index of the other array. Increase a counter each time there's a match, and you'll be able to get a ratio of matches. If you use an integer as a counter, remember that division with integers acts funky, so you'd need to throw to a double:
double aDoubleNumber = (double) intNumber / anotherIntNumber
The problem would be easier if we consider them set. Let you have two set -
Set<Integer> s1 = //a HashSet of Integer;
Set<Integer> s2 = //a HashSet of Integer;
Now make a copy of s1 for example s11 and do the following thing -
s1.retainAll(s2);
Now s1 contains only element of both sets - that is the intersection.
After that you can easily calculate the percentage
Edit: You can convert the array to a set easily by using the following code snippet (I am assuming you have array of int) -
Set<Integer> s1 = new HashSet<Integer>(Arrays.asList(somePrimiteiveIntArray));
I think this trick will works for other primitive type also.
Hope this will help.
Thanks a lot.
I am going to attempt to beat a dead horse and explain the easiest (conceptual) way to approach this problem I will include some code but leave a lot up to interpretation.
You have two arrays so I would change the overall method to something like this:
public double getPercentage(int[] arrayA, int[] arrayB) {
double percentage=0;
for(/*go through the first array*/) {
for(/*go through second array*/) {
if(arrayA[i]==arrayB[j]) { /*note the different indices*/
percentage++; /*count how many times you have matching values*/
/* NOTE: This only works if you don't have repeating values in arrayA*/
}
}
}
return (percentage/arrayA.length)*100; /*return the amount of times over the length times 100*/
}
You are going to move through the first array with the first loop and the second array with the second loop. So you go through every value in arrayB for each value in arrayA to check.
In my approach I tried storing the winning numbers in a Hashset (one pass iteration, O(n) )
And when iterating on the numberList, I would check for presence of number in Hashset and if so, I will increment the counter. (one pass iteration, so O(n) )
The percentage is thus calculated by dividing the counter with size of array.
See if the sample code makes sense:
import java.util.HashSet;
public class Arraycomparison {
public static void main(String ... args){
int[] arr0 = {1,4,2,7,6,3,5,0,3,9,3,5,7};
int[] arr1 = {5,2,4,1,3,7,8,3,2,6,4,4,1};
HashSet set = new HashSet();
for(int j = 0; j < arr1.length; j++){
set.add(arr1[j]);
}
double counter = 0;
for(int i = 0; i < arr0.length; i++){
if(set.contains(arr0[i])){
counter++;
}
}
System.out.println("Match percentage between arrays : " + counter/arr0.length*100);
}
}
You should use List over array, because that's a convenient way, but with array:
public class Winner {
public static void main(String... args) {
double result = getPercentThatMatch(new int[]{1,2,3,4,5}, new int[]{2,3,4,5,6});
System.out.println("Result="+result+"%");
}
public static double getPercentThatMatch(int[] winningNumbers,
int[] numberList) { // it is confusing to call an array as List
int match = 0;
for (int win : winningNumbers) {
for (int my : numberList ){
if (win == my){
System.out.println(win + " == " + my);
match++;
}
}
}
int max = winningNumbers.length; // assume that same length
System.out.println("max:"+max);
System.out.println("match:"+match);
double devide = match / max; // it won't be good, because the result will be intm so Java will trunc it!
System.out.println("int value:"+devide);
devide = (double) match / max; // you need to cast to float or double
System.out.println("float value:"+devide);
double percent = devide * 100;
return percent;
}
}
Hope this helps. ;)
//For unique elements
getpercentage(arr1, arr2){
res = arr1.filter(element=>arr2.includes(element))
return res.lenght/arr2.lenght * 100;
}
//For duplicate elements
getpercentage(arr1, arr2){
const setA = Set(arr1);
const setB = Set(arr2);
Let res = [ ];
for(let i of setB){
if(setA.has(i)){
res.push(i);
}
}
return res.lenght/setA.size* 100;
Below code works fine but it is in the complexity of O(n^2). Is it possible to do it O(n) or O(log n) time.
public class TwoRepeatingElements {
public static void main(String[] args) {
Integer array[] = {4, 2, 4, 5, 2, 3, 1, 2};
findTwoRepeatingElements(array);
}
private static void findTwoRepeatingElements(Integer[] array) {
int i, j;
for(i = 0; i < array.length-1; i++) {
for(j = i+1; j < array.length-1; j++) {
if(array[i] == array[j]) {
System.out.println(array[i]);
}
}
}
}
}
Obviously you can't find it in less than O(n), since you need to scan the whole array.
You can use hastable for a O(n) solution.
Just insert your elements in a hastable as you go and stop when the element you are to insert is already there.
private static void findTwoRepeatingElements(Integer[] array) {
Set<Integer> set = new HashSet<Integer>();
for(int a : array) {
if(!set.add(a)) {
System.out.println(a);
break;
}
}
}
You can sort the array and then just look for two equal numbers in adjacent positions.
This solution runs in O(n) time, notice that if you only need to find one repeated element, you can exit the loop as soon as you find it:
private static void findTwoRepeatingElements(Integer[] array) {
Set<Integer> seen = new HashSet<Integer>();
for (Integer i : array) {
if (seen.contains(i))
System.out.println(i);
else
seen.add(i);
}
}
EDIT
If you need to print the repeated elements only once, this solution uses a little more memory since two sets are needed, but it's still O(n). Take a look at this:
private static void findTwoRepeatingElements(Integer[] array) {
Set<Integer> seen = new HashSet<Integer>();
Set<Integer> repeated = new HashSet<Integer>();
for (Integer i : array)
if (!seen.add(i) && repeated.add(i))
System.out.println(i);
}
Create a temporary hashmap and put all values you encounter into this. The average look up time for a hashmap is O(1), thus you'd end with O(n).
O(log n) is absolutely impossible, since you need to iterate over the entire array at least once.
If you know beforehand what range of integers are possible, and it's a relatively small range, you can use a boolean[] to keep track of what integers you've already seen. That would be O(n+k), where k is the size of the range, and therefore O(n) if k is in O(n). Otherwise, you can use a HashSet<Integer>, though that would not be guaranteed O(n) time.
This can be reduced to O(n)
int previous =array[0];
for(int i=1; i less than array.length; i++) {
if (previous == array[i] return true;
previous =array[i];
}
return false // outside of loop.
Forgive the formatting I'm on my mobile
Similar to Peter's answer, but using the API better and thus with less code:
static Integer findFirstRepeatedElement(Integer[] array) {
Set<Integer> set = new HashSet<Integer>();
for(Integer a : array) {
if(!set.add(a)) // returns false if the element is already in the set
return a;
}
return null;
}
Edited: I notice he has now fixed his previous non-leet implementation
Given this array
int [] myArray = {5,-11,2,3,14,5,-14,2};
You are to find the maximum sum of the values in any downsequence in an unsorted array of integers. If the array is of length zero then maxSeqValue must return Integer.MIN_VALUE.
You should print the number, 19 because the downsequence with the maximum sum is 14,5.
Downsequence number is a series of non-increasing number.
These are the codes that i used but i guess that there are some cases which is still not accounted for.
Any ideas, thanks in advance.
public class MaxDownSequence{
public int maxSeqValue(int[] a){
int sum=Integer.MIN_VALUE;
int maxsum=Integer.MIN_VALUE;
for (int i=1;i<a.length;i++){
if(a[i]<a[i-1]){
sum = a[i] + a[i-1];
if (sum>maxsum){
maxsum=sum;
}
}
else {
sum=a[i];
if (sum>maxsum){
maxsum=sum;
}
}
}
if (a.length==0){
return Integer.MIN_VALUE;
}
else{
return maxsum;
}
}
public static void main(String args[]){
MaxDownSequence mySeq = new MaxDownSequence();
int [] myArray = {5,-11,2,3,14,5,-14,2};
System.out.println(mySeq.maxSeqValue(myArray));
}
}
Take the input {3,2,1} the answer should be 6 your program gives 5.
Your approach is correct, every time you test a number in the array you check if its less than (actually this should be <=) previous array element.
If it is you update sum as: sum = a[i] + a[i-1]; this is incorrect. sum in your program represents the running rum of the current subsequence. You should not be overwriting it.
Dynamic programming is the way to go.
http://en.wikipedia.org/wiki/Dynamic_programming
I know, maybe that doesn't help at all, but since I don't want to post a solution for your problem the best thing I can do is to give you this hint :)
you haven't considered sequences of more than two numbers. If you had [3,2,1] the result should be 6. But your code would give 5, because it only looks at the sum of the current number and the previous, whereas you should keep track of a current downsequence and add the current number to the running total of that downsequence. Once you hit a number that breaks the downsequence update maxsum if needed then reset the running total to 0.
not sure why you have the else in the loop?? If a[i] is not less than a[i-1] then it is not a downsequence, therefore surely maxsum should not be updated. If you take just the first 3 numbers in your sample array, it would return the number 2. Because the first downsequence [5,-11] would give a sum of -6 and on the next iteration it would just look at 2, which is greater than -6 and therefore maxsum is updated.
No need for:
if (a.length==0){
return Integer.MIN_VALUE;
}
if the array length is 0 then you never enter the loop and therefore never change maxsum, so it will still be equal to Integer.MIN_VALUE, so you can just return maxsum at the end regardless.
You are suppose to have a running sum i think. Meaning Sum = Sum + A[i]. Just make sure to initialize the sum to the first member of the array and you are in business.
package sree;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.NestingKind;
public class MaximumSumSequence {
private final int[] theArray;
private MaximumSumSequence(int[] theArray) {
this.theArray = theArray;
}
private void maximumSequence() {
int currentMax = 0,currentSum = 0, start = 0, end = 0, nextStart = 0;
for (int i=0; i< theArray.length; i++) {
currentSum += theArray[ i ];
if (currentMax < currentSum) {
currentMax = currentSum;
start = nextStart;
nextStart = end;
end = i;
} else if (currentSum < 0) {
currentSum = 0;
}
}
System.out.println("Max Sum :" + currentMax);
System.out.println("Start :" + start);
System.out.println("End :" + end);
}
public static void main(String[] args) {
//int[] anArray = {4, -1, 2, -2, -1, -3};
int[] anArray ={-2, 1, -3, 4, -1, 2, 1, -5, 4};
new MaximumSumSequence(anArray).maximumSequence();
}
}