In [1]:
from typing import List, Set, Dict, Tuple
Problem 9. 3Sum
https://leetcode.com/problems/3sum/
실행시간 비교
풀이 | 방식 | Big-O | 실행시간 순위 |
---|---|---|---|
1 | 브루트 포스로 계산 | O(n³) | 2위 |
2 | Two Pointer | O(n²) | 1위 |
Solution 1. 브루트 포스로 계산
In [8]:
def three_sum_1(nums: List[int]) -> List[List[int]]:
results = []
nums.sort()
# 브루트 포스 3회 반복
for i in range(len(nums)-2):
# 중복된 값 건너뛰기
if i > 0 and nums[i] == nums[i-1]:
continue
for j in range(i+1, len(nums)-1):
if j > i+1 and nums[j] == nums[j-1]:
continue
for k in range(j+1, len(nums)):
if k > j+1 and nums[k] == nums[k-1]:
continue
if nums[i] + nums[j] + nums[k] == 0:
results.append([nums[i], nums[j], nums[k]])
return results
In [9]:
three_sum_1([-1,0,1,2,-1,-4])
Out[9]:
Solution 2. Two Pointer
In [13]:
def three_sum_2(nums: List[int]) -> List[List[int]]:
results = []
nums.sort()
# 브루트 포스 3회 반복
for i in range(len(nums)-2):
# 중복된 값 건너뛰기
if i > 0 and nums[i] == nums[i-1]:
continue
# two pointer로 간격 좁혀가며 계산
left, right = i+1, len(nums)-1
while left < right:
sum = nums[i] + nums[left] + nums[right]
if sum < 0:
left += 1
elif sum > 0:
right -= 1
else:
# sum = 0으로 조건 만족하므로 정답 처리
results.append([nums[i], nums[left], nums[right]])
# 중복 피하기
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
# 이동하면서 다음 턴으로 넘어가기
left += 1
right -= 1
return results
In [14]:
three_sum_2([-1,0,1,2,-1,-4])
Out[14]:
Problem 10. Array Partition 1
https://leetcode.com/problems/array-partition-i/
실행시간 비교
풀이 | 방식 | Big-O | 실행시간 순위 |
---|---|---|---|
1 | 오름차순 풀이 | O(n) | 3위 |
2 | 짝수번째 값만 계산 | O(n) | 2위 |
3 | Pythonic way : slicing and sum | O(n) | 1위 |
Solution 1. 오름차순 풀이
In [103]:
def array_pair_sum_1(nums: List[int]) -> int:
sum = 0
pair = []
nums.sort()
for n in nums:
# 앞에서부터 오름차순으로 두 개의 원소를 페어로 만들어 합 산출
pair.append(n)
if len(pair) == 2: # pair안에 원소가 2개만 들어선 순간
sum += min(pair) # pair안의 합을 sum에 더해주기
pair.clear() # pair 초기화
return sum
In [104]:
array_pair_sum_1([1,4,3,2])
Out[104]:
Solution 2. 짝수번째 값만 계산
In [106]:
def array_pair_sum_2(nums: List[int]) -> int:
sum = 0
nums.sort()
for i,n in enumerate(nums):
# 짝수 번째 값의 합 계산
if i % 2 == 0:
sum += n
return sum
In [107]:
array_pair_sum_2([1,4,3,2])
Out[107]:
Solution 3. Pythonic way : slicing and sum
In [108]:
def array_pair_sum_3(nums: List[int]) -> int:
return sum(sorted(nums)[::2])
In [109]:
array_pair_sum_3([1,4,3,2])
Out[109]:
Problem 11. Product of Array Except Self
풀이 | 방식 | Big-O | 실행시간 순위 |
---|---|---|---|
1 | 교재 : 변수를 변화시키는 방법 | O(n) | 비슷 |
2 | 내 풀이 : slicing과 eval을 이용 | O(n) | 비슷 |
Solution 1 교재 풀이 방식 : 변수를 변화시키는 방법
In [111]:
def product_except_self_1(nums: List[int]) -> List[int]:
out = []
p = 1
# 왼쪽 곱셈의 결과 산출
for i in range(0, len(nums)):
out.append(p)
p = p * nums[i]
p = 1 # p의 초기화
# 왼쪽 곱셈 결과에 오른쪽 값을 차례대로 곱셈
for i in range(len(nums)-1, 0-1, -1):
out[i] = out[i] * p
p = p * nums[i]
return out
In [136]:
product_except_self_1([1,2,3,4])
Out[136]:
Solution 2 내 풀이 방식 : slicing과 eval을 활용
In [29]:
# 첫번째 시도 : 가다듬어 지지 않아 left, right의 초깃값이 매끄럽지 않음
def product_except_self_2(nums: List[int]) -> List[int]:
nums = list(map(str, nums)) # eval을 활용하기 위해 nums의 원소 타입 변경
left, right = [['1']], [] # left는 ['1']로 시작하므로 미리 값을 할당하고 시작
for i in range(1,len(nums)): # 자기 자신을 제외한 양쪽 부분을 리스트로 생성하여
left.append(nums[0:i]) # 왼쪽 파트는 left에 리스트 형태로 원소를 추가하고
right.append(nums[i:]) # 오른쪽 파트는 right에 리스트 형태로 원소를 추가함
right.append(['1']) # right는 ['1']로 끝나므로 마지막에 원소 추가
print(f'left : {left}')
print(f'right : {right}')
# left와 right의 값을 순서대로 서로 곱하여 ans에 추가
ans = [eval('*'.join(l)) * eval('*'.join(r)) for l,r in zip(left, right)]
return ans
In [30]:
# 생성된 중간 산출물 left, right와 답안 확인
product_except_self_2([1,2,3,4])
Out[30]:
In [31]:
# 조금 더 가다듬어진 형태의 풀이
# 결과와 방식은 위와 같지만, left와 right 자체가 숫자로 구성되며
# ['1']을 따로 추가해줬던 설정 두 번이 제거되었다.
def product_except_self_3(nums: List[int]) -> List[int]:
nums = list(map(str, nums))
left, right = [1]*len(nums), [1]*len(nums)
for i in range(1,len(nums)):
left[i] *= eval('*'.join(nums[0:i]))
right[i-1] *= eval('*'.join(nums[i:]))
print(f'left : {left}')
print(f'right : {right}')
ans = [l*r for l,r in zip(left,right)]
return ans
In [32]:
# 순서대로 left, right, ans 결과값 확인
product_except_self_3([1,2,3,4])
Out[32]:
Problem 12. Best Time to Buy and Sell Stock
풀이 | 방식 | Big-O | 실행시간 순위 |
---|---|---|---|
1 | 브루트 포스 | O(n) | 2위 |
2 | 저점을 기준으로 한 차이 계산 | O(n) | 1위 |
Solution 1. 브루트 포스
In [21]:
def max_profit_1(prices: List[int]) -> int:
# 최대 이득 초깃값 설정
max_price = 0
for i, price in enumerate(prices): # 구입 시점
for j in range(i, len(prices)): # 판매 시점
max_price = max(prices[j] - price, max_price) # max(현재 이득, 기록된 최고 이득)
return max_price
In [22]:
max_profit_1([7,1,5,3,6,4])
Out[22]:
Solution 2. 저점을 기준으로 한 차이 계산
최저점과 최대 이득 두가지를 모두 계속 갱신해나가는 방식
In [25]:
import sys
def max_profit_2(prices: List[int]) -> int:
profit = 0
min_price = sys.maxsize
# 최솟값과 최댓값을 계속 갱신
for price in prices: # 현재 가격
min_price = min(min_price, price) # 최저점 갱신
profit = max(profit, price - min_price) # 최대 이득 갱신
return profit
In [26]:
max_profit_2([7,1,5,3,6,4])
Out[26]:
출처 : 파이썬알고리즘인터뷰
'Python > Algorithm' 카테고리의 다른 글
[Python] Linked List (2) (0) | 2021.09.02 |
---|---|
[Python] Linked List (1) (0) | 2021.09.01 |
[Python] Array (1) (0) | 2021.08.30 |
[Python] 문자열 조작 (0) | 2021.08.23 |