sky54521
sky54521

Reputation: 61

use java8 stream api to accumulation find index for limit 10

I am learning java8 stream api. igot face this problem. Here have 9 number "1,2,3,4,5,6,7,8,9". I want find n for 1+2+3+....+n>=10 . How can I use java8 stream api to find n?

i tried use for loop to find n, code like this:

int sum,n=0;
for(int i=0;i<arr.length;i++){
    sum+=arr[i]
    if(sum>=10){
        n=i;
        break;
    }
}

Upvotes: 1

Views: 140

Answers (2)

Holger
Holger

Reputation: 298153

Your code is contradicting your problem description. You say that you want n such that 1+2+3+....+n>=10, but you are assigning i, the index of n in the array to n. Theses two correlate only if you have these ascending numbers in the array, but if you assume that fixed content, you wouldn't need the array at all.

Further, you are not incrementing sum at all; it's zero all the time.

If you assume a sequence of ascending integers only, you can get n without iterating:

int threshold = 10;

long n = Math.round(Math.sqrt(threshold*2));//that's it
System.out.println("solution: n = "+n);

// the rest is only verification and reporting
long actualSum = LongStream.rangeClosed(1, n).sum();
assert actualSum >= threshold;
assert actualSum - n < threshold;

System.out.println(LongStream.rangeClosed(1, n)
    .mapToObj(String::valueOf).collect(Collectors.joining(" + ")));
System.out.println("\t = "+actualSum+" >= "+threshold);

If you want to get the solution for an arbitrary sequence stored in an array, a loop is the simplest and most efficient sequential solution:

int i, sum;
for(i = 0, sum = 0; i < arr.length && sum < threshold; i++) sum += arr[i];

if(sum >= threshold) {
    System.out.println("solution: index = "+(i-1)+", n = "+arr[i-1]);
    System.out.println(Arrays.stream(arr, 0, i)
            .mapToObj(String::valueOf).collect(Collectors.joining(" + ")));
    System.out.println("\t = "+sum+" >= "+threshold);
} else {
    System.out.println("No solution with this array");
}

If you have a large array and want to utilize parallel processing, you may use

Arrays.parallelPrefix(arr, Integer::sum);
int i = Arrays.binarySearch(arr, threshold);
if(i < 0) i = -i-1;

if(i < arr.length){
    System.out.println("solution: index = "+i+", n = "+(arr[i]-(i==0? 0: arr[i-1])));
    System.out.println(arr[0]+" + "+IntStream.rangeClosed(1, i)
        .mapToObj(ix -> String.valueOf(arr[ix]-arr[ix-1]))
        .collect(Collectors.joining(" + ")));
    System.out.println("\t = "+arr[i]+" >= "+threshold);
} else {
    System.out.println("No solution with this array");
}

But this modifies the array. This modification is reversible, as the example demonstrates, we can print the original sequence, but such a modification may not always be feasible. If we have to make a copy or transform the array back to its original state, we may already lose any advantage of parallel processing, so the loop stays the best option in these cases. You need a sufficiently large array anyway, to have a chance of getting a performance benefit from parallel processing.

Upvotes: 1

Slava Vedenin
Slava Vedenin

Reputation: 60104

int n = IntStream.range(0, arr.length)
        .filter(i -> Arrays.stream(arr).limit(i + 1).sum() >= 10)
        .findFirst()
        .orElse(-1);
System.out.println(n); // return 3 (1 + 2 + 3 + 4 = 10)

Upvotes: 3

Related Questions