использовать API потока java8 для накопления найти индекс для предела 10 - PullRequest
0 голосов
/ 01 июня 2018

Я изучаю Java API Stream Java.igot сталкиваются с этой проблемой.Здесь есть 9 числа «1,2,3,4,5,6,7,8,9».Я хочу найти n для 1 + 2 + 3 + .... + n> = 10.Как я могу использовать java8 stream api, чтобы найти n?

я пытался использовать цикл for, чтобы найти n, код такой:

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

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Ваш код противоречит описанию вашей проблемы.Вы говорите, что хотите n , такой, что 1+2+3+....+n>=10, но вы присваиваете i, index из n в массиве n.Эти два коррелируют, только если у вас есть эти возрастающие числа в массиве, но если вы предполагаете, что это фиксированное содержимое, вам вообще не понадобится массив.

Кроме того, вы вообще не увеличиваете sum;это ноль все время.

Если вы предполагаете последовательность только восходящих целых чисел, вы можете получить n без итерации:

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);

Если вы хотите получитьРешение для произвольной последовательности, хранящейся в массиве, цикл является самым простым и наиболее эффективным последовательным решением:

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");
}

Если у вас большой массив и вы хотите использовать параллельную обработку, вы можете использовать

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");
}

Но это модифицирует массив.Эта модификация является обратимой, как показывает пример, мы можем напечатать оригинальную последовательность, но такая модификация не всегда может быть осуществимой.Если нам нужно сделать копию или преобразовать массив обратно в исходное состояние, мы уже можем потерять какое-либо преимущество параллельной обработки, поэтому цикл остается лучшим вариантом в этих случаях.В любом случае вам нужен достаточно большой массив, чтобы иметь возможность получить выигрыш в производительности от параллельной обработки.

0 голосов
/ 01 июня 2018
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)
...