포스트

[공부] 백준 3273 두 수의 합(투포인터 문제)

[공부] 백준 3273 두 수의 합(투포인터 문제)

📝 문제


🔍 문제 상황

문제 상황1 문제 상황2

예제 입력 1


1
2
3
9
5 12 7 10 9 1 2 3 11
13

예제 출력 1

1
3

💡 해결 방법 / 접근 방식

  • 투 포인터를 활용하여 접근해야함

투 포인터란(Two Pointers)?

투 포인터 설명 그림

  • 출처: https://velog.io/@tmdwns1521/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%88%AC-%ED%8F%AC%EC%9D%B8%ED%84%B0-Two-Pointers
  • 이름 그대로 포인터를 2개 써서 배열에 순차적으로 접근(순회)하는데, 특정 조건을 만족하는 값을 빠르게 찾는 알고리즘을 말합니다.
  • 이때 포인터는 실제 C/C++의 포인터 개념(우리가 아는 포인터(int* iPtr;))과는 다르고, 배열의 “위치”를 가리키는 두 변수를 의미합니다.
  • 보통 한 포인터는 배열의 시작부터, 다른 포인터는 끝에서부터 시작하며, 두 포인터의 이동 규칙을 잘 정의하면 완전 탐색(O(N^2))보다 효율적으로 동작(O(NlogN) 또는 O(N))합니다.

접근 방식

  • 우선 정렬을 안해주어도 문제없지만, 정렬해주면 편하기에 오름차순으로 정렬해줍니다.
  • 그 후에 left(왼쪽 포인터)는 시작점(0)으로, right(오른쪽 포인터)는 끝점(n-1)에서 시작합니다.
  • 두 숫자의 합(sum = v[left] + v[right])이 x와 같은지 비교하는데 이때
    • 합이 x보다 작으면, left(왼쪽 포인터) 값이 작으므로 left(왼쪽 포인터)를 증감시킵니다.
    • 합이 x보다 크면, right(오른쪽 포인터) 값이 크므로 right(오른쪽 포인터) 감소시킵니다.
    • 합이 x와 같으면, 쌍이므로 cnt를 증가하고, right(오른쪽 포인터)를 감소 시킵니다.
  • 두 포인터가 교차하면 종료됩니다.

🛠️ 구현 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    cin.tie(0)->sync_with_stdio(0);

    int n, x;
    cin >> n;
    // 수열을 벡터로 입력 받기
    vector<int> v(n);
    for (int i = 0; i < n; ++i) {
        cin >> v[i];
    }
    cin >> x;

    // 정렬 안해줘도 되지만 하면 좋음
    sort(v.begin(), v.end());

    // 왼쪽 포인터, 오른쪽 포인터 선언
    int left = 0, right = n - 1;
    // 카운터 선언
    int cnt = 0;
    // 포인터의 위치(값이)가 최종적으로 서로 만났을(같아졌을) 때 최종 종료됨
    // 이걸 쓰는 이유가 완탐시 시간 복잡도를 줄일 수 있음
    while (left < right) {
        int sum = v[left] + v[right];
        if (sum == x) {
            // 카운트 증가 및 오른쪽 포인터 감소
            cnt++;
            right--;
        } else if (sum > x) {
            // 오른쪽 포인터 값이 크므로 감소시키기
            right--;
        } else {
            // 왼쪽 포인터 값이 작으므로 증감시키기
            left++;
        }
    }
    cout << cnt;
    return 0;
}

🧷 결론

  • 이번 문제는 투 포인터에 대한 개념과 구조를 파악하기에 용이한 문제라고 판단됩니다.
  • 그래서 투 포인터를 이해하고자 한다면 반드시 풀어보면 좋은 문제이며, 이를 응용해서 투 포인터 유형의 문제를 풀어보면 좋을 것 같습니다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

인기 태그