배열에서 두 수의 합이 s가 되는 경우의 수(서로 다른 방향으로 움직이는 투 포인터)
배열이 서로 다른 원소들로 이루어져있고 정렬되어 있을때, 여기서 고른 서로 다른 두 수의 합이 s가 되는 경우의 수를 구하는 문제
투 포인터로 어떻게 해결할 수 있을까
보통 투 포인터하면 i = 0, j = 0으로 같은 방향에서 시작해서 j를 1씩 계속 증가시키다가, 특정 조건에서 멈추고
다시 i를 1 증가시키고 다시 j를 계속 증가시키고... 같은 방향으로 움직이지만
두 수 A[i] + A[j] = s가 될려면 i = 0으로 고정되어 있을 때 A[j] = s - A[0]로 확정적으로 구할 수 있다.
그러면 배열 A가 서로 다른 수로 이루어져 있고 정렬되어 있으므로
모든 i = 0,1,2,..,n-1는 작은 수부터 시작하므로 반대편 A[j] = s - A[i]는 큰 수부터 시작해야한다.
그래서 i = 0,1,2,..,n-1로 움직이면 j = n-1,n-2,n-3,....,0으로 반대편에서 서로 거꾸로 움직이면 된다.
i = 0일때, j = n-1부터 시작해서 A[i] + A[j] > s이면, j를 1 감소시키면 A[i] + A[j]가 점점 작아져서 s에 가까워진다
그러다가 A[i] + A[j] = s가 되는 순간 counting하고 j를 1 다시 감소시킨다.
그러면 A[i] + A[j] < s가 되므로 j를 감소시키는 반복문을 탈출하고 i를 1 증가시켜서 위 과정을 반복한다
i를 1 증가시키면 A[i]가 증가하므로 A[j]는 증가하지 않아야한다.
즉 j를 다시 n-1로 이동시킬 필요 없이 현재 j부터 시작해서 계속 감소시키면 된다.
또한 배열의 모든 수가 서로 다르므로 i에 맞는 j는 오직 하나밖에 없다
from sys import stdin
n,s = map(int,stdin.readline().split())
A = []
for _ in range(n):
a = int(stdin.readline())
A.append(a)
j = n-1
count = 0
for i in range(n):
while i < j:
v = A[i] + A[j]
if v == s:
count += 1
break
elif v > s:
j -= 1
else:
break
print(count)
'알고리즘 > 투 포인터 알고리즘' 카테고리의 다른 글
절댓값을 풀어내는 필수 테크닉 - 모든 i,j에 대해 (i-j)|ai-bj|의 합을 빠르게 구하는 방법 (0) | 2024.10.24 |
---|---|
겹치는 직선 구간쌍의 개수 빠르게 세기 (0) | 2024.08.02 |
투 포인터로 원소를 삭제하면서 가장 긴 수열을 찾을 수 있을까? (0) | 2023.06.08 |
투 포인터 올바르게 생각하기 기본문제로 연습2 (0) | 2023.04.12 |
투 포인터 기억해야할 점 - 끝 포인터를 처음으로 옮기지 않기 (0) | 2023.04.11 |