Найти все пары чисел в массиве, которые складываются до заданной суммы

Найти все пары чисел в массиве, которые складываются до заданной суммы

1. обзор

В этом кратком руководстве мы покажем, как реализовать алгоритм поиска всех пар чисел в массиве, сумма которых равна заданному числу. Мы сосредоточимся наtwo approaches to the problem.

При первом подходе мы найдем все такие пары независимо от уникальности. Во втором мы найдем только уникальные числовые комбинации, удалив лишние пары.

Для каждого подхода мы представим две реализации - традиционную реализацию с использованием шлюповfor и вторую с использованием Java 8 Stream API.

2. Вернуть все подходящие пары

Мы будем перебирать массив целых чисел, находя все пары (i иj), которые в сумме дают заданное число (sum), используя метод грубой силы и вложенного цикла. . This algorithm will have a runtime complexity of O(n2).

Для наших демонстраций мы будем искать все пары чисел, сумма которых равна6, используя следующий массивinput:

int[] input = { 2, 4, 3, 3 };

При таком подходе наш алгоритм должен возвращать:

{2,4}, {4,2}, {3,3}, {3,3}

В каждом из алгоритмов, когда мы находим целевую пару чисел, которая в сумме дает целевое число, мы собираем эту пару с помощью служебного методаaddPairs(i, j).

Первый способ реализации решения - это использовать традиционный циклfor:

for (int i = 0; i < input.length; i++) {
    for (int j = 0; j < input.length; j++) {
        if (j != i && (input[i] + input[j]) == sum) {
            addPairs(input[i], sum-input[i]));
        }
    }
}

Это может быть немного примитивно, поэтомуlet’s also write an implementation using the Java 8 Stream API.

Здесь мы используем методIntStream.range to для создания последовательного потока чисел. Затем мы фильтруем их по нашему условию:number 1 + number 2 = sum:

IntStream.range(0,  input.length)
    .forEach(i -> IntStream.range(0,  input.length)
        .filter(j -> i != j && input[i] + input[j] == sum)
        .forEach(j -> addPairs(input[i], input[j]))
);

3. Вернуть все уникальные подходящие пары

В этом примере нам потребуетсяdevelop a smarter algorithm that returns only the unique number combinations, omitting redundant pairs.

Для этого мы добавим каждый элемент в хэш-карту (без сортировки), сначала проверяя, была ли пара уже показана. Если нет, мы извлечем и отметим его, как показано (установите полеvalue какnull).

Соответственно, используя тот же массивinput, что и раньше, и целевую сумму6, наш алгоритм должен возвращать только разные числовые комбинации:

{2,4}, {3,3}

Если мы воспользуемся традиционным шлюпомfor , мы получим:

Map pairs = new HashMap();
for (int i : input) {
    if (pairs.containsKey(i)) {
        if (pairs.get(i) != null) {
            addPairs(i, sum-i);
        }
        pairs.put(sum - i, null);
    } else if (!pairs.containsValue(i)) {
        pairs.put(sum-i, i);
    }
}

Обратите внимание, что эта реализация улучшает предыдущую сложность, какwe use only one for loop, so we’ll have O(n).

Теперь решим проблему с помощью Java 8 и Stream API:

Map pairs = new HashMap();
IntStream.range(0, input.length).forEach(i -> {
    if (pairs.containsKey(input[i])) {
        if (pairs.get(input[i]) != null) {
            addPairs(input[i], sum - input[i]);
        }
        pairs.put(sum - input[i], null);
    } else if (!pairs.containsValue(input[i])) {
        pairs.put(sum - input[i], input[i]);
    }
});

4. Заключение

В этой статье мы объяснили несколько разных способов найти все пары, которые суммируют данное число в Java. Мы увидели два разных решения, каждое из которых использовало два основных метода Java.

Как обычно, все примеры кода, показанные в этой статье, могут бытьfound on GitHub - это проект Maven, поэтому его должно быть легко скомпилировать и запустить.