Search

[백준] 수 고르기

서론

오늘의 코딩 테스트 문제는 '수 고르기'다. 백준 2230번. 투 포인터 알고리즘을 사용해 해결했다.

문제 요약

N개의 정수로 이루어진 수열에서 두 수를 고른다.
두 수의 차이가 M 이상이면서 가장 작은 경우를 찾는다.
1 ≤ N ≤ 100,000
0 ≤ M ≤ 2,000,000,000
0 ≤ |A[i]| ≤ 1,000,000,000

접근 방식

1.
수열을 오름차순으로 정렬한다.
2.
투 포인터 알고리즘을 사용한다.
왼쪽 포인터를 기준으로 오른쪽 포인터를 이동시킨다.
차이가 M 이상이 되면 결과를 갱신하고 왼쪽 포인터를 이동한다.
3.
최소 차이를 찾을 때까지 반복한다.

코드

#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int N, M; cin >> N >> M; vector<int> A(N); for (int i = 0; i < N; i++) cin >> A[i]; sort(A.begin(), A.end()); pair<int, int> answer = {*(A.begin()), *(A.end()-1)}; int l = 0, r = 0; while (l < N) { while (((r + 1) < N) && ((A[r] - A[l]) < M)) { r++; } if ((A[r]-A[l]) >= M && (answer.second-answer.first) > (A[r]-A[l])) { answer = {A[l], A[r]}; } if (A[l]-A[r]==M) break; l++; } cout << answer.second - answer.first << endl; return 0; }
C++
복사

구현 과정

1.
입력 받은 수열을 정렬했다.
2.
두 개의 포인터(l, r)를 초기화했다.
3.
왼쪽 포인터가 끝에 도달할 때까지 반복했다:
오른쪽 포인터를 이동시키며 차이가 M 이상이 되는 지점을 찾았다.
조건을 만족하면 결과를 갱신했다.
차이가 정확히 M이면 즉시 종료했다.
4.
최종 결과를 출력했다.

회고

1.
투 포인터 알고리즘을 사용해 O(N)의 시간 복잡도로 해결할 수 있었다.
2.
뭐 정렬에 O(N log N)이 소요되는 거 같지만, 전체적으로는 효율적인 해결책이다.
3.
Copilot이 켜져 있어서 그냥 풀었는데, 덕분에 변수 잘 못 쓰고 한참 헤매었다.
4.
투 포인터 알고리즘 관련 문제를 더 풀어볼 예정이다.