[LeetCode] 238. Product of Array Except Self
nums
배열 원소의 모두 곱한 값에서 해당 원소를 나눈 값을 출력하는 문제이다. 문제에서는 나눗셈하면 안 된다고 명시하고 있으므로 나눗셈하지 않고 풀어야 하는 게 포인트이다.
- 나눗셈을 하지 않아야 함.
- T=O(n), S=O(1)으로 풀어본다.
따라서 위의 두 가지를 목표로 이 문제를 해결해 보려고 한다.
Ideation
nums = [1, 2, 3, 4]
의 경우를 살펴보자.
기대하는 정답은 [24, 12, 8, 6]
이다. 해당 배열이 나오기 위해서는 전체 값의 곱(1*2*3*4 = 24
)에 각자의 원소를 나누면 된다.
전체 곱에서 자신을 나누어 나오는 값은 자신을 제외한 모든 값의 곱과 동일하다.
e.g. 원소 3을 기준으로 한다면
1*2*3*4 / 3
===1*2*4
이다.
따라서 우리는 자신을 제외한 곱들의 왼쪽과 오른쪽을 곱해주면 정답이 된다는 것을 알 수 있다.
e.g. 원소 3을 기준으로 3의 좌/우의 곱은
1*2
*4
=8
이다.
그러므로 왼쪽의 곱들과 오른쪽의 곱들을 기억해 두고 각 원소별 값을 출력해 주면 해결할 수 있다.
해당 원소까지의 왼쪽, 오른쪽 곱셈 값은 누적 배열을 활용하면 된다.
e.g. 원소 n 기준 왼쪽
[n-2, n-2 * n-1]
*[n+1, n+1 * n+2]
오른쪽
Implementation(T=O(n), S=O(n))
위의 정리를 토대로 구현을 해보자.
- n 번째 원소의 왼쪽 곱의 값들을 저장한다.
- n 번째 원소의 오른쪽 곱의 값들을 저장한다.
- 전체 원소를 순회하며 n 번째 원소의 좌우 값의 곱을 저장한다.
- 리턴한다.
위의 구현으로 문제를 해결할 수 있지만 공간 복잡도가 O(n)
이기 때문에 더 최적화가 가능하다.
Implementation(T=O(n), S=O(1))
좌우 배열은 결국 마지막에 곱하기 위해서만 존재한다.
따라서 굳이 저장하지 않고 바로바로 곱해나가면 공간복잡도를 O(1)
으로 줄일 수 있다.
NOTE: 어쨌든 answers 배열을 사용하므로 정확히는 O(n)이지만
LeetCode에서 return 배열(answers)이 아닌 추가 배열을 사용하지 않는다는 것으로 O(1)으로 취급하고 있다.
연속되는 곱셈의 합을 이용한 재밌는 문제였다.
그럼 이만~