코딩테스트/문제풀이

[220801] Level1_ 체육복

Honey Badger 2022. 8. 3. 00:21

https://school.programmers.co.kr/learn/courses/30/lessons/42862

 

프로그래머스

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

programmers.co.kr

초기 아이디어

1. 이중 for문을 돌려 '체육복을 분실한 그룹'과 '여분의 체육복을 가져온 그룹'의 공집합을 찾아 없앤다. 

2. 그렇게 하면 체육복을 분실한 사람중 여분의 체육복이 있는 사람은 제외할 수 있다. 

3. 체육복을 분실했고 여분의 체육복도 없는 lost가 체육복을 분실하지도 않고 여분의 체육복도 가져온 그룹에게 빌린다.

4. 앞뒤번호에게만 빌릴 수 있기 때문에 자기 앞번호에게 우선적으로 빌려주고 그다음 뒷번호에게 빌려주는 식으로 한다.

 

오류 & 해결

 피드백을 받은 결과 함수의 매개변수로 들어온 값은 되도록 건드리지 않는게 좋다. const 선언을 통해 명시적으로 보여주어도 좋다. 내가 푼 방법은 erase 메서드를 이용해 집합 안의 값들을 지워주는 방식을 사용했는데 아예 전체 학생을 대상으로 기록부 같은 것을 만드는 방식으로 변경했다. ex) 3번학생 : 체육복의 개수 2개 이런식으로. 그리고 첫번째 학생과 마지막 학생은 빌려줄 수 있는 사람이 한사람이므로 예외처리 해주어야 한다. 

 

#include <vector>

using namespace std;

int solution(int n, vector<int> lost, vector<int> reserve) {
    int answer = 0;
    vector<pair<int, int>> Students;
    Students.reserve(n);
    for (int i = 0; i < n; ++i)
    {
        Students.push_back(make_pair(i, 1));
    }
    for (unsigned int i = 0; i < lost.size(); i++)
    {
        Students[lost[i]-1].second -= 1;
    }
    for (unsigned int i = 0; i < reserve.size(); i++)
    {
        Students[reserve[i]-1].second += 1;
    }

    vector<pair<int, int>>::iterator iter;
    for (iter = Students.begin(); iter != Students.end(); ++iter)
    {
        int clothes = iter->second;
        if (iter == Students.begin()) 
        {
            if (clothes == 2 && (iter+1)->second < 1)
            {
                (iter+1)->second += 1;
                continue;
            }
            else continue;
        }
        else if (iter == Students.end() - 1)
        {
            if (clothes == 2 && (iter - 1)->second < 1)
            {
                (iter - 1)->second += 1;
                continue;
            }
            else continue;
        }
        else
        {
            if (clothes == 2 && (iter - 1)->second < 1)
            {
                (iter - 1)->second += 1;
                continue;
            }
            else if (clothes == 2 && (iter + 1)->second < 1)
            {
                (iter + 1)->second += 1;
                continue;
            }
        }       
    }
    for (iter = Students.begin(); iter != Students.end(); ++iter)
    {
        if (iter->second >= 1)
            answer += 1;
    }

    return answer;
}

모범답안

1. 좀 더 단순하게 생각하자.

2. 배열의 index를 학생번호로 간주하면 pair를 쓸 이유가 없어진다.

3. 굳이 체육복을 한개씩 처음에 주지 않아도 된다.

4. 처음학생과 마지막학생의 예외를 처리해줄 필요도 없다. 0번째사람은 참조해도 무방하고 문제에서 학생수는 2명이상 30명이하라고 가정했으므로 마지막 다음을 참조해 벗어난범위 오류를 내지 않는다.

5. 맨 마지막에 순회하여 체육복갯수를 셀 필요가 없다. 처음에 answer을 전체 학생수로 초기화한다음, else를 통해 체육복이 없으면서 앞사람 뒷사람도 빌려줄 수 없는 경우를 빼주면 되기 때문. 

#include <vector>
using namespace std;
int student[35];
int solution(int n, vector<int> lost, vector<int> reserve) {
    int answer = n;
    for(int i : reserve) student[i] += 1;
    for(int i : lost) student[i] += -1;
    for(int i = 1; i <= n; i++) {
        if(student[i] == -1) {
            if(student[i-1] == 1) 
                student[i-1] = student[i] = 0;
            else if(student[i+1] == 1) 
                student[i] = student[i+1] = 0;
            else
                answer -= 1;
        }
    }
    return answer;
}