Я хочу найти сумму target
в массиве, добавляя целые числа, пока она не будет достигнута, а затем вернуть индексы, которые складываются в цель, используя потоки.
Например, если предоставленный массив — это {1, 2, 3, 4}
, а target
— это 4
, метод должен распечатать массив int, состоящий из индексов {0,2}
, но не делает этого.
Код выглядит следующим образом:
public static int[] twoSum(int[] numbers, int target) {
IntStream.of(0, numbers.length - 1).boxed()
.flatMap(i -> IntStream.range(i , numbers.length - 1).boxed()
.filter(j -> numbers[j] + numbers[i] == target)
.flatMap(j -> Stream.of(new int[]{i , j}, new int[] {j,i})))
.forEach(num -> System.out.println(Arrays.toString(num)));
return numbers;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(twoSum(new int[]{1,2,5,1}, 4)));
}
Да, это должна быть цель, я просто жестко запрограммировал цель какое-то время, но я также изменил ее на int[] b = Arrays.stream(numbers).filter((x -> num[finalI] + x == 4) ).toArray(); который работал. Но по какой-то причине возвращается пустой массив
Приведите пример исходного массива и ожидаемого результата. Например, каким должен быть результат для массива 1, 4, 3, 0, 4, 1
и целевой суммы 4
?
Если бы целевая сумма была равна 4, она вернула бы индекс 0 и индекс 2, потому что сумма этих элементов равна 4.
Я думал о создании Instream.range(0, number.length-1).boxed, который мог бы действовать как начальный цикл for, а затем о создании другого потока, который бы сравнивал все индексы с исходным потоком в штучной упаковке.
Для начала опишем возможные пути решения проблемы:
Map
, который будет хранить все пары элементов, получающихся в результате, в целевую сумму. Алгоритм работает за линейное время На). Требуется только две итерации по исходному массиву.В приведенном ниже решении представлена потоковая реализация подхода, использующего Map
.
В качестве первого шага нам нужно сгенерировать карта, который будет связывать значение, которое необходимо добавить к определенному элементу, чтобы получить сумму target
(ключ) и индекс элемента массива (ценность).
Затем создайте поток по индексам данного массива, отфильтруйте первый элемент, который соответствует ключ в карта, и создайте на его основе массив двузначный.
Если результат не найден - вернуть пустой массив.
public static int[] twoSum(int[] numbers, int target) {
Map<Integer, Integer> sumMap = getSumMap(numbers, target);
return IntStream.range(0, numbers.length)
.filter(i -> sumMap.containsKey(numbers[i]))
.mapToObj(i -> new int[]{i, sumMap.get(numbers[i])})
.findFirst()
.orElse(new int[0]);
}
public static Map<Integer, Integer> getSumMap(int[] numbers, int target) {
rreturn IntStream.range(0, numbers.length)
.boxed()
.collect(Collectors.toMap(
i -> target - numbers[i], // a key - dif between target sum and a current element
Function.identity(), // a value - index of the current element
(left, right) -> left)); // resolving duplicates
}
main()
- демо
public static void main(String[] args) {
System.out.println(Arrays.toString(twoSum(new int[]{1, 4, 3, 0, 4, 1}, 4)));
}
Выход
[0, 2] // indices of the first pair of elements (1, 3) that can produce the sum of `4`
не могли бы вы объяснить назначение Function.identity() в getsummap?
Не уверен, но если вы используете именно этот код, возможно, это из-за опечатки после foreach. Вы инициируете ввод как nu
, но печатаете его как num
.
.forEach(num -> System.out.println(Arrays.toString(num)));
Возможно, замена этого на то, что у вас есть, решит проблему.
РЕДАКТИРОВАТЬ
Что касается дополнительных пояснений по комментариям, выяснилось, что это проблема с заданными значениями и не имеет ничего общего с API потока Java.
Вместо использования цикла for вы можете вложить два IntStreams
для получения желаемого результата (насколько я понимаю). Это вернет все пары, сумма которых равна целевому значению. Это не включает элементы массива, которые добавили сами к себе равные цели. Таким образом, для цели 4
[2, 2]
в результате не включается
int[] arr1 = { 1, 2, 3, 4, 5, -2, -1, -3, -4, -5 };
int[][] array = twoSum(arr1, 4);
for (int[] a : array) {
System.out.println(Arrays.toString(a));
}
отпечатки
[1, 3]
[5, -1]
boxed
, чтобы преобразовать int в объект.flatMap
(объединяете вложенные потоки в один) другой IntStream
начиная с одного большего, чем предыдущий поток, но полной длины массива.flatMap
и используя значения IntStreams
в качестве индексов для предоставленного массива, отфильтруйте значения, которые не суммируются с целью, и создайте массив из двух чисел, которые складываются (это также может быть заменены индексами массива, если это необходимо).public static int[][] twoSum(int[] numbers, int target) {
return IntStream.range(0, numbers.length - 1)
.boxed()
.flatMap(i -> IntStream.range(i + 1, numbers.length)
.filter(k -> numbers[i] + numbers[k] == target)
.mapToObj(k -> new int[] { numbers[i],numbers[k] }))
.toArray(int[][]::new);
}
Не добавляя
.boxed()
.int[] b = Arrays.stream(numbers).filter((x -> num[finalI] + x == 4)).toArray();
А разве так не должно быть== target
?