Алгоритм — Комбинации, из четырех и сумма

Используя последовательность: 1, 2, 3, 4, 5.

Я искал комбинации из:

  • Один
  • Два
  • Три
  • Четыре

Объяснение и пример

В следующем примере приведены комбинации:

  • Один
  • Два
  • Три
  • Четыре

Комбинации расположены по столбцам. Каждый столбец представляет собой комбинацию количества чисел, которые он содержит.

Прочитайте образец сверху вниз.

Образец:

1
  1 2
    1 2 3
      1 2 3 4
      1 2 3 5
    1 2 4
      1 2 4 5
    1 2 5
  1 3
    1 3 4
      1 3 4 5
    1 3 5
  1 4
    1 4 5
  1 5
2
  2 3
    2 3 4
      2 3 4 5
    2 3 5
  2 4
    2 4 5
  2 5
3
  3 4
    3 4 5
  3 5
4
  4 5
5
Войти в полноэкранный режим Выход из полноэкранного режима

Задание

Возьмите каждое число и объедините его с каждым последующим. Затем возьмите следующее число и сделайте то же самое.
Последний элемент в комбинациях из одного числа игнорируйте.

Например, для входной последовательности A:

A[1] A[2], A[1] A[3], to A[1] A[A.length]
Войти в полноэкранный режим Выйти из полноэкранного режима
A[2] A[3], A[2] A[A.length]
Войти в полноэкранный режим Выйти из полноэкранного режима

Повторяя действия до конца.

COMBINATIONS-OF-TWO(A)
  combinations = [];
  count = 1;
  for i=1 to A.length - 1
    for j=i+1 to A.length
      combinations[count] = [i, j];
      count++;
  return combinations;
Вход в полноэкранный режим Выход из полноэкранного режима

Выводы и реализация

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

Один

Комбинации из одного элемента берут каждый элемент из массива.

Два

Комбинации из двух берут каждую комбинацию из одного.
Затем добавляем каждый последующий элемент к каждому.
Игнорируя последний элемент в комбинации один.

Три

Комбинации из трех берут каждую комбинацию из двух.
Затем добавьте каждый последующий элемент к каждому.
Игнорируя последние 2 элемента в комбинации один.
Игнорирование последнего 1 элемента в комбинации два.

Четыре

Комбинация из четырех берется каждая комбинация из трех.
Затем добавьте каждый последующий элемент к каждому.
Игнорирование последних 3 элементов в комбинации один.
Игнорирование последних 2 элементов в комбинации два.
Игнорирование последних 1 элементов в комбинации три.

Реализация

COMBINATIONS-OF-FOUR(A)
  combinations = [];
  // use counter because loops
  // don't track amount combinations
  count = 1;

  // combinations of one
  for i to A.length - 3

    // combinations of two
    for j=i+1 to A.length - 2

      // combinations of three
      for z=j+1 to A.length - 1

        // each subsequent element
        // on top of combination of three
        // gives combination of four
        for k=z+1 to A.length
          combinations[count] = [i, j, z, k];
          count++;

  return combinations;
Вход в полноэкранный режим Выход из полноэкранного режима

В качестве бонуса, вот реализация с помощью JavaScript. Copy-Paste runnable.

function combinationsOfFour(A) {
  let combinations = [];
  let count = 0;
  let i, j, z, k;
  const len = A.length;

  for (i = 0; i < len - 3; i++) {
    for (j = i + 1; j < len - 2;j++) {
      for (z = j + 1; z < len - 1; z++) {
        for (k = z + 1; k < len; k++) {
          combinations[count] = [i, j, z, k];
          count++;
        }
      }
    }
  }

  return combinations;
}

const numbers = [0, 1, 2, 3, 4];
console.log(combinationsOfFour(numbers));
Вход в полноэкранный режим Выйти из полноэкранного режима

Поиск действительных сумм из 4

Теперь я модифицирую алгоритм. Мне нужно вернуть четверки с индексами, значения которых совпадают с суммой.

// find sums of 4 that match sum
SUMS-OF-FOUR(A, sum)
  sums = [];
  // use sum counter because loops
  // don't track amount of sums we have
  count = 1;

  // combinations of one
  for i to A.length - 3
    for j=i+1 to A.length - 2
      for z=j+1 to A.length - 1
        for k=z+1 to A.length
          // if combination of four
          // is the sum we need
          if A[i] + A[j] + A[z] + A[k] == sum
            // save the indices representing sum
            sums[count] =[i, j, z, k];
            count++;

  return sums;
Войти в полноэкранный режим Выйти из полноэкранного режима

Сколько циклов мне нужно?

Я выяснил, сколько циклов мне нужно. Я сделал это, наблюдая за поведением, которое я использовал.

Используя последовательность 1, 2, 3, 4, 5 получаем комбинации по одной.

1
2
3
4
5
Вход в полноэкранный режим Выход из полноэкранного режима

Это было линейно. Теперь сделайте это для комбинаций из двух.

Используя последовательность 1, 2, 3, 4, 5, получите комбинации из двух чисел.

Первое число:

1
  append 2 => 1, 2
  append 3 => 1, 3
  append 4 => 1, 4
  append 5 => 1, 5
Вход в полноэкранный режим Выход из полноэкранного режима

Второе число:

2
  append 3 => 2, 3
  append 4 => 2, 4
  append 5 => 2, 5
Войти в полноэкранный режим Выход из полноэкранного режима

Заметили поведение цикла? Я делал это постоянно. Прошло несколько часов, пока я понял, сколько итераций делает мой ум.

Используя математическую индукцию, мы пришли к следующему выводу

  1. Мы можем повторить шаги для комбинации из n.
  2. Комбинации из одного числа используют один цикл и являются линейными.
  3. Комбинации из двух используют два цикла и являются квадратичными.
  4. Комбинации из трех используют три цикла и являются кубическими.

Реализация комбинаций для любого допустимого r

Используя последовательность 1, 2, 3, 4, 5.

Даны преобразования до уровня 3, или r=3.

1
  1 2
    1 2 3
    1 2 4
    1 2 5
  1 3
    1 3 4
    1 3 5
  1 4
    1 4 5
  1 5
2
  2 3
    2 3 4
    2 3 5
  2 4
    2 4 5
  2 5
3
  3 4
    3 4 5
  3 5
4
  4 5
5
Вход в полноэкранный режим Выход из полноэкранного режима

Мы можем рассматривать столбцы как уровни или комбинации r. Каждая комбинация является преобразованием предыдущей. Чтобы добраться до комбинации 2, мы преобразуем каждую комбинацию 1. Для каждой предыдущей комбинации мы берем последнее значение (индекс). Затем добавляем каждый последующий индекс к этой комбинации. Это дает нам новую комбинацию. При последующих итерациях создается одинаковое количество комбинаций. Исключение составляют начальные комбинации, они пусты. Мы должны их заполнить. Мы продолжаем преобразовывать комбинации, пока не исчерпаем количество значений на уровне. Нам нужен один уровень для каждого преобразования.

Реализация

COMBINATIONS(array, r, combinations = [])
  if combinations.length == 0
    // populate combinations of 1
    for i=1 to array.length
      combinations[i] = [i]

  if r > 1
    // next combinations
    next = []
    count = 1
    // transform each combination
    // to next one
    for i=1 to combinations.length
      // take current combination
      c = combinations[i]
      // take last index
      last = c[c.length]
      // append next indexes to
      // current combination
      for j=last+1 to array.length
        // copy current combination
        next[count] = c
        // append index to current comb.
        // which creates new one
        next[count][c.length + 1] = j
        count++

    COMBINATIONS(array, r-1, next)
  else
    return combinations
Вход в полноэкранный режим Выход из полноэкранного режима

Ограничения, которые необходимо учитывать

  • массив должен быть массивом чисел
  • 1 <= r <= ar
    • информация: из 5 чисел нельзя составить неповторяющуюся комбинацию 6
    • информация: комбинации из 0 не имеют смысла?
  • Комбинации должны быть либо
    • пустой массив (из-за начального значения)
    • массив чисел

Оцените статью
devanswers.ru
Добавить комментарий