교훈
Given an integer array
nums
, return an arrayanswer
such thatanswer[i]
is equal to the product of all the elements of nums exceptnums[i]
.
answer[i]
에는nums[i]
를 제외한 다른 모든 요소의 곱이 들어간다.
The product of any prefix or suffix of
nums
is guaranteed to fit in a 32-bit integer.
nums
의 요소들은 모두 32비트 정수다.
You must write an algorithm that runs in
O(n)
time and without using the division operation.
O(n)
에 풀어야 하며, 나눗셈을 사용해서는 안된다.
Example 1:
Input: nums = [1,2,3,4]
Output: [24,12,8,6]
Example 2:
Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]
Constraints:
2 <= nums.length <= 105
-30 <= nums[i] <= 30
nums
is guaranteed to fit in a 32-bit integer.Follow up: Can you solve the problem in O(1)
extra space complexity? (The output array does not count as extra space for space complexity analysis.)
O(n^2)
에 풀기class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
ret = [1] * len(nums)
for i in range(len(nums)):
for j in range(len(nums)):
if i == j:
continue
ret[i] *= nums[j]
return ret
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
p = 1
for i in range(len(nums)):
p *= nums[i]
ret = [p] * len(nums)
for i in range(len(ret)):
ret[i] //= nums[i]
return ret
일단 나눗셈을 사용했으므로 틀린 답안이지만, 알고리즘 자체에도 오류가 있다.
nums
의 요소 중에 0이 하나라도 있으면 틀린다.
1. p
= 0을 가지게 되므로 ret
배열은 0으로 채워지고, 아무리 다른 값으로 나눠봤자 값을 되찾을 수 없다.
2. nums[i]
가 0이라면 ZeroDivisionError
에 빠진다.
따라서, 처음부터 p를 계산할 때 0이 들어있는 경우는 빼고 계산하여야 한다.
굳이 만들어보자면 다음과 같은 코드가 나온다.
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
p = 1
zero_appeared = False
zero_idx = -1
for i in range(len(nums)):
if nums[i] == 0:
if zero_appeared: # 0이 두개
return [0] * len(nums)
zero_appeared = True
zero_idx = i
continue
p *= nums[i]
if zero_appeared: # 0이 1개
ret = [0] * len(nums)
ret[zero_idx] = p
return ret
ret = [p] * len(nums)
for i in range(len(ret)):
ret[i] //= nums[i]
return ret
Success
Runtime: 224 ms, faster than 97.56% of Python3 online submissions for Product of Array Except Self.
Memory Usage: 21.2 MB, less than 58.64% of Python3 online submissions for Product of Array Except Self.
통과는 했다...
아쉽게도 LeetCode 채점 서버에는 나눗셈 연산자를 사용했는지 판별하는 기능은 없었다.
[a, b, c, d, e]
가 있다고 해보자.
한번 순회를 하면서
[1, a, a*b, a*b*c, a*b*c*d]
을 가지는 새로운 배열을 만들어보자.
이번에는 역으로 순회를 하면서
[e*d*c*b, e*d*c, e*d, e, 1]
을 가지는 새로운 배열을 만들어보자.
이 새로운 배열 2개를 스칼라곱(내적)하면,
[(e*d*c*b), (e*d*c)*(a), (e*d)*(a*b),(e)*(a*b*c), (a*b*c*d)]
를 얻을 수 있다. 이거 생각한 사람은 진짜 천재다.
Follow up: Can you solve the problem in O(1)
extra space complexity? (The output array does not count as extra space for space complexity analysis.)
에 대해 생각해보자면,
두번째 새로운 배열은 굳이 만들 필요 없이 첫번째 새로운 배열에 덮어씌우는 식으로 만들고, 곱해지고 있는 값은 p
라는 변수 하나에 계속 갱신하면 된다.
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
ret = []
p = 1
for i in range(len(nums)):
ret.append(p)
p *= nums[i]
p = 1
for i in range(len(nums) - 1, - 1, -1):
ret[i] *= p
p *= nums[i]
return ret