Как я могу собрать результат из вложенного .forEach в Java IntStream - PullRequest
0 голосов
/ 30 сентября 2018

Я играю и пытаюсь решить эту проблему "Две суммы" с помощью Java Stream, не используя императивный метод:

Given nums = [2, 7, 11, 15], target = 18,
Because nums[1] + nums[2] = 7 + 11 = 18,
return [1, 2].

А вот мой частично работающий код.Кто-нибудь может помочь решить?Я просто не могу понять, как собрать его обратно, чтобы он был возвращен в виде примитивного массива int:

class Solution { 
    public int[] twoSum(int[] input, int target) {
        IntStream.range(0,  input.length)
           .forEach(i -> {
               IntStream.range(0,  input.length)
                   .filter(j -> i != j && input[i] + input[j] == target)
                   .peek(t -> System.out.println(input[t]))
                   .findFirst();
               }
            );
        return null;
    }
}

И вот результат выше (из peek):

11
7

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Обычный рецепт для имитации вложенных циклов for, которые управляют списком или массивом через индексы, заключается в использовании IntStream вместе с flatMap:

int[] input = {12, 7, 11, 15, 6, 2};
int target = 18;

List<List<Integer>> result = IntStream.range(0, input.length)
    .boxed()
    .flatMap(i -> IntStream.range(i + 1, input.length)
        .filter(j -> input[i] + input[j] == target)
        .mapToObj(j -> Arrays.asList(i, j)))
    .collect(Collectors.toList());

System.out.println(result); // [[0, 4], [1, 2]]

Обратите внимание, что вам не нужноPair класс для поддержания состояния из внутреннего потока во внешний поток, потому что вы можете применить необходимый фильтр к внутреннему потоку.

Кроме того, внутренний IntStream не требуется для запуска на 0, потому что вы не хотите, чтобы в результате были [i, j] и [j, i] (нужен только один из них).Так что начинать внутренний IntStream с i + 1 достаточно.

0 голосов
/ 30 сентября 2018

Проблема должна быть решена с временной сложностью O (n):

Map<Integer, List<Integer>> indexMap = IntStream.range(0, a.length).boxed().collect(Collectors.groupingBy(i -> a[i]));

IntStream.range(0, a.length)
    .boxed()
    .filter(i -> indexMap.containsKey(target - a[i]))
    .flatMap(i -> indexMap.get(target - a[i]).stream().filter(j -> i < j).map(j -> Pair.of(i, j)))
    .forEach(System.out::println);
0 голосов
/ 30 сентября 2018

Как я уже говорил в комментариях, потоки не всегда являются идеальным решением.Но что касается вашей задачи, похоже, вам нужен поток Pair.К сожалению, в Java нет кортежей (например, Scala), поэтому я предлагаю создать простой Pair класс.

class Pair {
    int i, j;
    public Pair(int i, int j) {
        this.i = i;
        this.j = j;
    }
}

Затем поработать с потоком пар

 IntStream.range(0,  input.length)
                .boxed()
                .flatMap(i -> IntStream.range(0,  input.length).boxed()
                                .map(j -> new Pair(i,j))
                )
                        .filter(p -> p.i != p.j)
                        .filter(p -> input[p.i] + input[p.j] == target)
                        .collect(toList());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...