백준 3273 - 두 수의 합 (Python3)
코드
n = int(input())
arr = list(map(int, input().split()))
x = int(input())
# 투 포인터는 정렬이 필요함
# 그래야 조건별로 값의 크기를 똑바로 비교할 수 있음
arr.sort()
# 시작과 끝 인덱스
start = 0
end = n-1
# 최종 정답 변수
cnt = 0
while start < end:
# 합이 x가 되면 개수를 1 증가
# 다음 start의 비교를 위해 1 증가
if (arr[start] + arr[end]) == x:
cnt += 1
start += 1
# 두 합이 x보다 작으면 start를 1 증가
# 오름차순 정렬이므로 start가 1 증가하면
# 해당 값 역시 증가한다 => x와 더 가까워짐
elif (arr[start] + arr[end]) < x:
start += 1
# 두 합이 x보다 크면 end를 1 감소
# end가 감소해야 start가 그대로일 때 값을 줄일 수가 있음
else:
end -= 1
print(cnt)
문제 해설
투 포인터를 활용한 문제.
이진 탐색과 매우 유사한 느낌의 알고리즘이다. 알고리즘의 이름에서 알 수 있듯이 리스트에서 두 개의 점을 찍어 두 점을 가운데로 점점 모아가면서 원하는 결과를 얻게 해주는 알고리즘이다.
간단한 로직은 아래와 같다.
- 주어진 리스트를 오름차순 정렬한다.
- 첫 번째 인덱스(start)와 마지막 인덱스(end)를 각각 변수에 저장한다.
- 첫 번째 요소와 마지막 요소의 합이 X와 같은지 비교한다.
- 같다면 개수 1 증가
- 크다면 end 1 감소 (마지막 요소가 가장 크므로 그 앞 요소는 이보다 작음)
- 작다면 start 1 증가 (첫 요소가 가장 작으므로 그 뒷 요소는 이보다 큼)
- 3의 과정을 start가 end보다 커질 때까지 반복한다.
주어진 리스트의 요소 중 2개를 뽑아 합이 X가 되게 만드는 것이 문제의 목표인데, 단순히 생각해봐도 이를 최대한 중복없이 검사하려면 리스트를 정렬해야겠다는 것이 직감적으로 떠올랐다. 처음 이 알고리즘을 접했을 때는 정말 알겠으면서도 막막한 느낌이었는데, 이진 탐색을 어느정도 연습한 상태여서 그런지 생각보다 쉽게 이해가 갔다. 앞으로 이런 성취감을 느낄 수 있도록 더더욱 열심히 문제를 풀어야겠다.
댓글남기기