문제출처 https://school.programmers.co.kr/learn/courses/30/lessons/178870

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 설명: 비내림차순(중복을 허용하는 오름차순) 수열이 주어질 때 임의의 두 원소와 그 사이의 원소를 모두 포함하는 부분 수열의 합이 k와 같을 때 두 원소의 값을 구하는 문제이다. 투포인터 알고리즘을 활용해야하며 아래의 조건을 만족해야한다.

조건) 합이 k인 부분 수열이 여러개인 경우 길이가 짧은 수열인 두 원소의 값을 찾고, 길이가 짧은 수열이 여러 개인 경우 시작 인덱스가 작은 두 원소의 값을 찾는다.

입출력 예를 통해 두 원소는 sequence의 2개의 인덱스로 이해하면 된다.

 

로직:

1. 투포인터 문제로 두개의 포인터를 사용하여 구해진 부분수열 합(누적 합)이 위 다중 조건에 만족하는 인덱스를 찾아 우선순위 큐에 저장하여 정렬을 한다.

2. 부분수열의 합이 정답인 k보다 작으면 pt2을 +1 증가시키고 증가된 pt2를  sequence[pt2]로 하여 sum에 더한다. 

3. 부분수열의 합이 정답인 k보다 크면 누적합인 sum에서 sequence[pt1] 값을 빼고 pt1을 +1 증가시켜 sequence[pt1]를 sum에 더한다.

4. pt2가 sequence 사이즈와 같아질 때까지 2번과 3번을 반복하며 k와 같은 sum의 pt1, pt2를 찾는다.

#include<bits/stdc++.h>
using namespace std;

// 부분 수열의 합이 k일 때 양 끝 점인 두개의 포인터 저장 용도.
struct node {
    int px1;
    int px2;
    int dist;
};
//다중 조건: 1순위 정렬) 합이 K인 부분 수열 여러개 인 경우 짧은 수열. 2순위 정렬) 길이가 짧은 수열 여러개 일 경우 인덱스 작은 순
bool operator<(node var, node tar) {
    if (tar.dist < var.dist)return 1;
    if (tar.dist > var.dist)return 0;
   return tar.px1 < var.px1;
}
vector<int> solution(vector<int> sequence, int k) {
    vector<int> answer;
    //우선순위 q를 통해 빠른 정렬(heap) 구현
    priority_queue<node> q;
    // 투포인터 구현 위한 변수 선언
    //pt1 좌측 끝점 포인터, pt2 우측 끝점 포인터  (투포인터)
    int pt1 = 0;
    int pt2 = 0;
    int sum = sequence[0];
    while (1) {
        if (pt1 == pt2) sum = sequence[pt1];
        if (sum < k) { // sum이 작으면 pt2를 증가시켜서 sum에 sequence의 pt2인덱스의 값을 더함.
            if (pt2 == 5) {
                cout << 1;
            }
            pt2++;
            if (pt2 == sequence.size())break; // range out 방지.
            sum += sequence[pt2];
        }
        else if (sum > k) { // sum이 크면 pt1을 인덱스로 가진 sequence배열의 값을 빼주고 pt1을 증가시킴./ 
            sum -= sequence[pt1];
            pt1++;
        }
        else { // sum == k 인 경우
            q.push({ pt1, pt2, pt2 - pt1 }); // 힙정렬
            sum -= sequence[pt1]; // 다음 순서를 위해 pt1 인덱스 값 지우고
            // pt1을 증가 시킴. 단, pt1과 pt2가 동일하다고 하면 pt2도 증가시켜야함.
            // pt1만 증가 되면 다음 차순에서는 sum이 k보다 작기에 pt2가 증가 되고 pt2의 인덱스값을 sum에 더해줄 것이다.
            if (pt1 == pt2) pt2++; 
            if (pt2 == sequence.size())break;
            pt1++; 
        }
    }
    // q의 첫 인덱스가 다중조건을 만족하는 첫번째 인덱스로 answer에 px1, px2 넣음.
    answer.push_back(q.top().px1);
    answer.push_back(q.top().px2);
    
    return answer;
}

 

 

회고: 투포인터 알고리즘 바로 알았지만 구현에 시행착오가 있었다. 

'PS > 프로그래머스' 카테고리의 다른 글

3진법 뒤집기  (0) 2023.07.29
[카카오 인턴] 키패드 누르기 [V]  (0) 2023.07.29
달리기 경주(O)  (0) 2023.07.28
두 원 사이의 정수 쌍(V)  (0) 2023.07.21
요격시스템 (-)  (0) 2023.07.21

+ Recent posts