Введение. Задача «Произведение массива, кроме самого себя» — это распространенная задача кодирования, требующая нахождения произведения всех элементов массива, кроме элемента с текущим индексом. Задача состоит в том, чтобы решить ее без использования деления и за O(n) временной сложности. Кроме того, последующий вопрос спрашивает, можно ли решить его с постоянной пространственной сложностью. В этой статье мы рассмотрим эффективный алгоритм решения этой проблемы и обсудим решения как оптимальной временной, так и пространственной сложности.
Постановка задачи: задан массив из n целых чисел, где n > 1, задача состоит в том, чтобы вернуть выходной массив, такой что output[i] равен произведению всех элементов входного массива, кроме nums[i].
Пример: при заданном входном массиве nums = [1, 2, 3, 4] алгоритм должен вернуть выходной массив [24, 12, 8, 6], так как произведение всех элементов, кроме nums[0], равно 24, произведение всех элементов, кроме nums[1], равно 12 и так далее.
Алгоритм: Чтобы решить эту проблему без использования деления и с временной сложностью O(n), мы можем использовать тот факт, что произведение всех элементов, кроме текущего, может быть вычислено путем умножения произведения всех элементов слева от текущего элемент с произведением всех элементов справа от текущего элемента.
Вот алгоритм достижения этого:
- Инициализировать выходной массив той же длины, что и входной массив, изначально заполненный 1.
- Переберите входной массив слева направо и для каждого элемента обновите выходной массив, умножив текущий продукт на произведение всех элементов слева от текущего элемента.
- Сбросьте текущий продукт до 1 и снова выполните цикл по входному массиву, но на этот раз справа налево. Для каждого элемента обновите выходной массив, умножив текущий продукт на произведение всех элементов справа от текущего элемента, и обновите текущий продукт, умножив его на текущий элемент.
- Верните выходной массив, который теперь содержит произведение всех элементов, кроме текущего элемента по каждому индексу.
Этот алгоритм имеет временную сложность O(n), так как мы дважды перебираем входной массив, и пространственную сложность O(n), поскольку мы используем дополнительный выходной массив той же длины, что и входной массив.
Реализация:
Вот реализация алгоритма в коде C:
/** * Return an array of size *returnSize. * Note: The returned array must be malloced, assume caller calls free(). */ int* productExceptSelf(int* nums, int numsSize, int* returnSize) { int total=1; int i=0; int zero=0; int* ans=(int*)malloc(sizeof(int)*numsSize); *returnSize=numsSize; for(i=0;i<numsSize;i++) { if(nums[i]!=0) total*=nums[i]; else zero++; } if(zero>1)//all zero total=0; if(zero>0) { for(i=0;i<numsSize;i++) { if(nums[i]==0) ans[i]=total; else ans[i]=0; } }else { for(i=0;i<numsSize;i++) { ans[i]=total/nums[i]; } } return ans; } Loop through the input array from left to right, and for each element, update the current product with the product of all elements to the left of the current element.
- Сбросьте текущий продукт до 1 и снова выполните цикл по входному массиву, но на этот раз справа налево.
return
ans;
}