Я видел решения в Интернете, но все решения имеют временную сложность O (n) или O (n ^ 2). Мне интересно, можно ли найти подмассив с суммой 0 в O (nlogn), который не использует вспомогательную структуру данных. Однако нам разрешено использовать рекурсию.

Можем ли мы изменить алгоритм максимальной суммы подмассива, чтобы найти решение этой проблемы?

Во входном массиве будут только единицы и -1, и алгоритм найдет подмассив с суммой 0.

Ввод = {1, 1, -1, 1, -1, -1, 1, -1}

Output = 1, 8 (1 - начальный индекс, а 8 - последний индекс)

В этом конкретном случае весь входной массив имеет сумму, равную 0. Таким образом, сообщенные начальный и конечный индексы равны 1 и 8 соответственно (при условии, что индексирование в массиве начинается с 1).

Изменить: мы можем использовать решение этой проблемы для решения другой проблемы. Эта проблема заключается в следующем.

Для массива arr из n целых чисел найдите самый длинный непрерывный подмассив с равным количеством четных и нечетных элементов. Ниже приведен пример (индексирование начинается с 1):

A = {8, 2, -3, 4, 9, 6}

Ответ: (2, 5). (2 - начальный индекс, 5 - последний индекс)

Единственное ограничение - алгоритм не может использовать какую-либо вспомогательную структуру данных. Решение должно быть наиболее эффективным при этом ограничении. Также разрешено использование рекурсии.

1
Abdullah Malik 14 Июн 2020 в 11:47

1 ответ

Лучший ответ

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

Практически это означает, что глубина рекурсии равна абсолютной совокупной сумме. Так, например, если массив равен [-1, -1, -1, 1], то рекурсия перейдет на глубину 3, и она вернется с уровня 3 на уровень 2 с возвращаемым значением true. На уровне 2 он вернет false, так как был обнаружен конец массива, и поэтому он выпадет из рекурсии.

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

Вот реализация этой идеи на JavaScript:

function zeroSum(arr) {
  let i = 0; // index in the input array, managed outside of recursion
  // Longest zero-sum interval so far. Zero based, and value at end index 
  //   is not part of the interval:
  let longest = [0, 0];

  function recur(dir) { // dir is the previous value from the array (if any)
    let start = i; // local variable
    while (i < arr.length) {
      let val = arr[i++];
      if (val == -dir) return true; // zero sum
      if (recur(val) && i - start > longest[1] - longest[0]) {
        longest[0] = start;
        longest[1] = i;
      }
    }
    return false; // no zero sum
  }

  recur(0); // 0 is passed to indicate there is no previous value
  return longest;
}

// demo
console.log(zeroSum([1, 1, -1, 1, -1, -1, 1, -1]));
0
trincot 14 Июн 2020 в 12:14