Pick peaks (5 kyu)

https://www.codewars.com/kata/5279f6fe5ab7f447890006a7

이번, kata는 주어진 목록에서, 로컬 Peak를 찾아서 반환하는 문제였다. 아래와 같이 0, 1, 2, 5, 1, 0에서는 3번 index의 5가 peak가 되므로 3, 5를 반환하면 된다.

For example, the array arr = [0, 1, 2, 5, 1, 0] 
has a peak at position 3 with a value of 5 
(since arr[3] equals 5).

아래의 경우는 로컬 peak가 '...3, 6, 4...'에서 한번, ...2, 3, 2...에서 한번 있기 때문에 3, 7번 index, 값은 6, 3을 반환해야 한다. 주의점은 로컬이기 때문에 peak가 여러개가 있을 수 있다. 그리고 peak값이 반복되는 경우는 시작 index를 기준으로 반환해야 한다.

Example: pickPeaks([3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3]) 
should return {pos: [3, 7], peaks: [6, 3]}

쉬운 문제로, 아래와 같이 간단한 코드로 마무리했다.
만약 peak 값이 반복되지 않는 다면 i-1, i, i+1의 값을 비교해서 i가 peak인지 여부를 체크해서 추가를 하면 되지만, 반복이 될 수 있기 때문에, 구간의 개념을 두었다.

구간이 시작하는 index를 start라고 정의하고,
i-1값보다 i가 크면 무조건 start를 i로 업데이트 하여, peak가 시작되는 index 찾도록 했다.

start가 초기값인 -1이 아닌 상태에서, i-1값이 i보다 크면, peak가 내려오기 시작하므로 start index에 해당하는 값을 peak값으로 보았다. 여기서 만약 i-1이 i와 같으면, 별다른 업데이트를 하지 않으므로, start는 peak가 시작되는 지점을 계속 가리켜 문제 조건을 만족할 수 있게 했다.

struct PeakData
{
    std::vector<int> pos, peaks;
};

PeakData pick_peaks(const std::vector<int> &v)
{
    PeakData result;

    if(v.size() < 3)
        return result;

    int start = -1;
    for (int i = 1; i < v.size(); ++i)
    { 
        int pre = v[i-1];
        int cur = v[i];
        
        if(pre< cur)
        {
            start = i;
        }
        else if(start != -1)
        {
            if(pre> cur)
            {
                result.pos.push_back(start);
                result.peaks.push_back(v[start]);
                start = -1;
            }
        }
    }

    return result;
}

추천 kata로 바로 올라와서 해봤는데, 깔끔하게 종료된 경우였다.

좋은 웹페이지 즐겨찾기