문제
https://www.acmicpc.net/problem/3151
3151번: 합이 0
Elly는 예상치 못하게 프로그래밍 대회를 준비하는 학생들을 가르칠 위기에 처했다. 대회는 정확히 3명으로 구성된 팀만 참가가 가능하다. 그러나 그녀가 가르칠 학생들에게는 큰 문제가 있었다.
www.acmicpc.net
문제 요약
N명의 학생들이 각 -10000 ~ 10000까지의 코딩 실력을 갖고 있다.
세 명의 학생들을 골라 코딩 실력이 0이 되는 3인조를 만들 수 있는 경우의 수를 출력한다.
+ 코딩 실력이 같은 학생들이 있을 수 있다.
코드
N = int(input())
arr = sorted(list(map(int, input().split())))
cnt = 0
# 한 개의 수 선택 후 투 포인터를 통해 나머지 두 개의 수 구하기
for i in range(N - 2):
left = i + 1
right = N - 1
max_idx = N
# max_id는 세 수 중 가장 큰 수. 중복된 수라면 가장 왼쪽에 있는 수의 인덱스 (초기 값: N)
while left < right:
tmp = arr[left] + arr[right]
if tmp < -arr[i]: # 합이 0보다 작은 경우
left += 1
elif tmp == -arr[i]: # 합이 0인 경우
if arr[left] == arr[right]:
# left원소와 right원소가 같으면 사이에 있는 원소도 같은 값 (정렬되어 있기 때문)
cnt += right - left
else:
# left원소와 right원소가 다른 경우
if max_idx > right: # max_id가 제대로 설정되지 않은 경우만
max_idx = right
while max_idx >= 0 and arr[max_idx - 1] == arr[right]:
max_idx -= 1
cnt += right - max_idx + 1
left += 1
else: # 합이 0보다 큰 경우
right -= 1
print(cnt)
코드 설명
입력 받은 코딩 실력 배열을 오름차순 정렬한다. (투 포인터 방식을 사용하기 위해)
1. 0 ~ N - 3번째 학생까지 한 명을 고정으로 선택하고, 나머지 두 명을 투 포인터 방식으로 선택한다.
+ 첫 번째 학생의 코딩 실력: arr[i]+ 두 번째 학생의 코딩 실력: arr[left]+ 세 번째 학생의 코딩 실력: arr[right]
+ max_idx는 세 번째 학생과 같은 실력을 가진 학생들 중 가장 왼쪽에 있는 학생의 인덱스 (초기: N)
2. 세 학생의 실력 합이 0보다 작으면 left인덱스를 1 증가시키고, 크면 right인덱스를 1 감소시키며 탐색한다.
3. 세 학생의 실력 합이 0인 경우,
3 - 1. left원소와 right원소가 같으면 그 사이에 있는 값들도 같은 값이므로 right - left 개수만큼 cnt를 증가시킨다.
ex) arr = [-6 3 3 3]
+ 정렬되어 있기 때문에 같은 값들이 모여 있다.
3 - 2. left원소와 right원소가 다를 경우, max_idx를 탐색하고 right - max_idx + 1 개수 만큼 cnt를 증가시킨다.
ex) arr = [-6 0 6 6 6]
3 - 3. left 인덱스를 1 증가시키고 다음 탐색을 진행한다.
4. cnt를 출력한다.
'Algorithm Problems > 투 포인터' 카테고리의 다른 글
[백준/Python] 1644번: 소수의 연속합 (2) | 2023.11.07 |
---|---|
[백준/Python] 26091번: 현대모비스 소프트웨어 아카데미 (1) | 2023.09.24 |
[백준/Python] 3273번: 두 수의 합 (0) | 2023.09.18 |
[백준/python] 1806번: 부분합 (2) | 2023.08.18 |
[백준/python] 14465번: 소가 길을 건너간 이유 5 (2) | 2023.08.18 |