알고리즘
백준 알고리즘(BOJ)_1253번['좋은 수' 구하기]
alswlfl
2022. 11. 18. 15:56
'좋은 수' 구하기[1253번]
Q. N개의 수 중에서 어떤 수가 다른 수 두 개의 합으로 나타낼 수 있다면 그 수를 “좋다(GOOD)”고 한다.
N개의 수가 주어지면 그 중에서 좋은 수의 개수는 몇 개인지 출력하라.
수의 위치가 다르면 값이 같아도 다른 수이다.
입력
첫째 줄에는 수의 개수 N(1 ≤ N ≤ 2,000), 두 번째 줄에는 i번째 수를 나타내는 Ai가 N개 주어진다. (|Ai| ≤ 1,000,000,000, Ai는 정수)
출력
좋은 수의 개수를 첫 번째 줄에 출력한다.
문제 분석
N의 개수가 최대 2,000이라 가정해도 좋은 수 하나를 찾는 알고리즘의 시간 복잡도는 N2보다 작아야 함
좋은 수 하나를 찾는 알고리즘의 시간 복잡도는 최소 O(nlogn)이어야 함
정렬된 리스트를 투 포인터 알고리즘을 사용하여 두 정수의 합이 해당 K값과 같은지 비교하면서 좋은 수 개수 구하기
(단, 정렬된 데이터에서 자기 자신을 좋은 수 만들기에 포함하면 안됨 → K의 인덱스 값과 두 수의 인덱스 값이 같으면 안됨
[투 포인터 이동 원칙]
• A[i]+A[j] > K: j--;
• A[i]+A[j] < K: i++;
• A[i]+A[j] == K: count++; 프로세스 종료
슈도코드 작성
1. 수의 개수 N입력받기
2. 리스트 A 입력받기
3. 리스트 A 정렬
4. for k in range(N): k가 N이 될때까지 탐색
i=0 포인터 값 초기화
j=N-1
K=A[k] 판별 대상인 수 K값 지정
while i<j: i와 j가 만나기 전까지 반복
투포인터 이동 원칙 이용
⭐️ k가 i와 같거나, k가 j가 같은 경우는 제외해주어야 함(자기 자신은 좋은 수 만들기에 포함하면 안됨)
5. 좋은 수의 개수 출력
코드 구현
import sys
input=sys.stdin.readline
N=int(input()) #수의 개수
A=list(map(int, input().split())) #N개의 수 값 A리스트
A.sort() #리스트 정렬
count=0
for k in range(N): #K가 N개가 될 때까지 반복
i=0 #i와 j를 배열 A 양쪽 끝에 위치
j=N-1
K=A[k]
while(i<j): #i와 j가 만나기 전까지 반복
#투 포인터 이동 원칙
if (A[i]+A[j])>K:
j-=1
elif (A[i]+A[j])<K:
i+=1
else:
if k==i: #자기 자신이 좋은 수가 되는 경우 제외
i+=1
elif k==j: #자기 자신이 좋은 수가 되는 경우 제외
j-=1
else:
count+=1 #count값 증가시키고
break #프로세스 종료
print(count)