Products of Array Except Self:
https://neetcode.io/problems/products-of-array-discluding-self/question

nums, 출력은 같은 길이의 배열 outputoutput[i] = nums[i]를 뺀 나머지 모든 원소의 곱처음에 Brute Force로 O(n^2) 으로 풀기
math 내장함수의 prod() 사용
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
import math
ans = []
for i in range(len(nums)):
left = math.prod(nums[:i])
right = math.prod(nums[i+1:])
ans.append(left*right)
return ans
-> math.prod(nums[:i]) -> O(n)
math.prod(nums[i+1:]) -> O(n)
이걸 n 번 반복하기 때문에 O(n^2)가 됨.
위와 같은 로직은 매 반복마다 새로운 리스트를 생성해서 메모리 낭비와 성능 저하를 일으킬 수 있음.
같은 곱을 계속 다시 계산하고 있는데, 이전 계산 결과를 재사용하는 방안으로 가야함
output[i] = 전체 곱 / nums[i] -> 문제에서 without using the division operationnums[i]를 제외한 모든 곱은 (i 왼쪽에 있는 숫자들의 곱) x (i 오른쪽에 있는 숫자들의 곱) 으로 생각하면 됨left[i] = i 왼쪽에 있는 값들의 곱), 오른쪽에서부터 누적 곱 배열을 만들어서 (right[i] = i 오른쪽에 있는 값들의 곱) 으로 output[i] = left[i] x right[i] 으로 하면 시간복잡도 O(n)이 문제의 핵심 ADT
left, right 두 개의 보조 배열을 만들어서, 누적 곱을 사용함
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
left = [1] * n
right = [1] * n
ans = [1] * n
for i in range(1, n):
left[i] = left[i-1] * nums[i-1]
for i in range(n-2, -1, -1):
right[i] = right[i+1] * nums[i+1]
for i in range(n):
ans[i] = left[i] * right[i]
return ans
-> 시간복잡도 O(n), 공간복잡도 O(n )
여기서 공간복잡도를 좀 더 줄이고 싶다면?
left 배열을 반환할 결과 배열에 바로 저장하고
right 배열을 변수 하나 postfix로 대체함
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [1] * n
prefix = 1
for i in range(n):
ans[i] = prefix
prefix *= nums[i]
postfix = 1
for i in range(n-1, -1, -1):
ans[i] *= postfix
postfix *= nums[i]
return ans
left[i]는 ans[i]에 미리 있고, right[i]만 뒤에서 오면서 곱해주면 됨
처음엔 left/right 배열로 풀고, left는 output에 저장하고 right는 postfix 변수로 처리해서 공간을 O(1)로 줄일 수 있다.
이렇게 되면 시간복잡도 O(n), 공간복잡도 O(1)로 풀어나갈 수 있음.