class Solution:
def two_sum_target(self, nums: List[int], target: int) -> List[int]:
for outer in range(len(nums) - 1): # 리스트 순회, 기준점 - (1)
for inner in range(outer + 1, len(nums)): # 리스트 순회, 기준점 이후 - (2)
if (nums[outer] + nums[inner] == target): # 두 수의 합이 타켓일 경우
return [outer, inner] # 결과 반환
test_case: List[int] = [2, 7, 11, 15] # 테스트 케이스
target = 17 # 타켓
solution = Solution()
result: List[int] = solution.two_sum_target(test_case, target) # 알고리즘 호출
print(result) # 결과 : [1, 2]
(1) len(nums)가 아닌 len(nums)-1로 한 이유는, 기준점과 그 기준점 이후의 수의 조합으로 타켓이 되는지를 검사하기 때문에, 기준점은 len(nums)-1까지만 순회하여도 충분
(2) range(outer, len(nums))가 아닌 range(outer + 1, len(nums))인 이유는, 기준점과 그 기준점 이후의 수의 조합으로 검사를 하기때문이다. 그렇게 검사하는 이유는, 기준점 이전의 수 조합으로 타켓이 가능하다면, 이전에 이미 검사가 끝났을 거기때문에, 이후로 하는 것이 합당하다.
시간복잡도 T(n) = n(n-3)/2 + 1 = O(n^2)
class Solution:
def two_sum_target(self, nums: List[int], target: int) -> List[int]:
for index, num in enumerate(nums): # 리스트 순회
complement: int = target - num # 타켓과의 차 계산
if complement in nums[index+1:]: # 차가 리스트에 존재하는지 검사 - (1)
return [index, nums[index+1:].index(complement) + (index + 1)] # 결과 반환 - (2)
test_case: List[int] = [2, 7, 11, 15] # 테스트 케이스
target = 18 # 타켓
solution = Solution()
result: List[int] = solution.two_sum_target(test_case, target) # 알고리즘 호출
print(result) # 결과 : [1, 2]
시간복잡도 T(n) = n(n-1)/2 = O(n^2)
브루트포싱 방법보다 실질적인 연산 수는 많지만 시간 복잡도는 동일하다. 하지만 파이썬 내부에 구현된 in 메소드덕분에 전자의 방법보다 더 빠른 속도를 보장한다.
class Solution:
def two_sum_target(self, nums: List[int], target: int) -> List[int]:
dict_nums: dict = {} # key : num, value : index의 형태로 dict 생성
for index, num in enumerate(nums): # 리스트 순회 - (1)
dict_nums[num] = index # 리스트의 index를 value, 리스트의 element를 key로 저장
for index, num in enumerate(nums): # 리스트 순회 - (1)
if (target - num in dict_nums) and (dict_nums[target - num] != index): # 더하여 target이 되는 수가 있을 경우 - (2)
return [index, dict_nums[target- num]] # 결과 반환
test_case: List[int] = [2, 7, 11, 15] # 테스트 케이스
target = 17 # 타켓
solution = Solution()
result: List[int] = solution.two_sum_target(test_case, target) # 알고리즘 호출
print(result) # 결과 : [1, 2]
class Solution:
def two_sum_target(self, nums: List[int], target: int) -> List[int]:
dict_nums: dict = {} # key : num, value : index의 형태로 dict 생성
for index, num in enumerate(nums): # 리스트 순회
if target - num in dict_nums: # 더하여 target이 되는 수가 있을 경우
return [index, dict_nums[target- num]] # 결과 반환
dict_nums[num] = index # 딕셔너리 삽입
class Solution:
def trap(self, height: List[int]) -> int:
if not height: # 빈 리스트일 경우
return 0 # 0 반환
volume: int = 0 # 쌓이는 물의 양
max_height_index: int = height.index(max(height)) # 가장 높은 블럭의 높이
left_height: List[int] = height[:max_height_index+1] # 가장 높은 블럭 기준 좌측
right_height: List[int] = list(reversed(height[max_height_index:])) # 가장 높은 블럭 기준 우측
left, right = 0, 1
while right < len(left_height):
if left_height[left] > left_height[right]: # 좌측 칸막이보다 높이가 낮은 경우
volume += left_height[left] - left_height[right] 좌측 칸막이와의 높이차만큼 물을 쌓는다
right += 1 # 칸막이 구간을 넓힌다
else: # 좌측 칸막이 벽의 높이보다 같거나 큰 경우
left, right = right, right + 1 # 다음 구간으로 넘어가기
left, right = 0, 1
while right < len(right_height):
if right_height[left] > right_height[right]: # 좌측 칸막이보다 높이가 낮은 경우
volume += right_height[left] - right_height[right] # 좌측 칸막이와의 높이차만큼 물을 쌓는다
right += 1 # 칸막이 구간을 넓힌다
else:
left, right = right, right + 1 # 다음 구간으로 넘어가기
return volume # 반환
test_case: List[int] = [0,1,0,2,1,0,1,3,2,1,2,1] # 테스트 케이스
solution = Solution()
result: int = solution.trap(test_case) # 알고리즘 호출
print(result) # 결과 : 6