Make Unreal REAL.
article thumbnail
2003. 수들의 합 2

 

 

전형적인 전진 투 포인터 문제다.

  • l, r이 모두 0부터 시작하는 투 포인터다.
  • 현재 값이 목표 값보다 크면 l을 하나씩 당겨주고, 작으면 r을 하나씩 늘려주는 방식이다.
  • 조건을 만족하는 가장 빠른 구간을 찾거나, 조건을 만족하는 구간의 개수를 찾을 때 유용하다.

 

l, r이 모두 n에 도달할 때까지 반복하고, 항상 l ≤ r이므로 r이 n에 도달한 이후에는 l만 증가시켜주는 로직이 들어가야 한다.

 

#include <iostream>
#include <vector>

using namespace std;

int TwoPointers(vector<int>& v, int M)
{
    int answer = 0;
    size_t n = v.size();
    int l = 0, r = 0, sum = v[0];

    while (l < n || r < n)
    {
        if (sum <= M)
        {
            answer += (sum == M);
            
            if (++r < n)
                sum += v[r];
            else
                sum -= v[l++];
        }
        else
        {
            sum -= v[l++];
        }
    }

    return answer;
}

int main(int argc, char* argv[])
{
    int N, M;
    cin >> N >> M;

    vector<int> v(N);
    for (int i = 0; i < N; ++i) cin >> v[i];

    cout << TwoPointers(v, M);

    return 0;
}

 

좀 더 간단한 방식이다.

 

전진 투 포인터에서는 범위를 [l, r)로 구성하는 것이 인덱스 계산이 쉽다.

  • 단, r의 범위 검사는 꼭 순서대로 중간에 위치해야 한다.

 

#include <iostream>
#include <vector>

using namespace std;

int TwoPointers(vector<int>& v, int M)
{
    int answer = 0;
    size_t n = v.size();
    int l = 0, r = 0, sum = 0;

    while (l <= r)
    {
        if (M <= sum)
            sum -= v[l++];
        else if (n <= r)
            break;
        else
            sum += v[r++];

        answer += (sum == M);
    }

    return answer;
}

int main(int argc, char* argv[])
{
    int N, M;
    cin >> N >> M;

    vector<int> v(N);
    for (int i = 0; i < N; ++i) cin >> v[i];

    cout << TwoPointers(v, M);

    return 0;
}

'자료구조 & 알고리즘 > 백준' 카테고리의 다른 글

12891. DNA 비밀번호  (0) 2023.09.16
21921. 블로그  (0) 2023.09.15
11441. 합 구하기  (0) 2023.09.14
11657. 타임머신  (0) 2023.09.13
1197. 최소 스패닝 트리  (0) 2023.09.11
profile

Make Unreal REAL.

@diesuki4

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그