Reputation: 61
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
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
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