[프로그래머스 Level1] 한 번에 맞추지 못한 문제

Wonjun·2022년 6월 10일
0
post-thumbnail

📝 같은 숫자는 싫어

문제 설명

같은 숫자는 싫어

해결 방법

#include <vector>
#include <iostream>

using namespace std;

vector<int> solution(vector<int> arr) 
{
    vector<int> answer;
    for(int i = 0; i < arr.size(); i++){
        if (arr[i] != arr[i + 1])
            answer.push_back(arr[i]);
    }
    return answer;
}

arr 원소의 i번째를 i + 1번째와 같은지 비교한다. 같지 않으면 중복되지 않았다는 것이므로 answer에 push_back() 했다.
❓위의 코드 제출 결과 마지막 테스트 케이스 17을 통과하지 못했다. 효율성 테스트는 모두 통과했다.
❗C++ reference를 참고해서 #include <algorithm>에 있는 unique 함수를 사용해서 해결하였다. unique 함수는 주어진 범위(answer.begin(), answer.end())에서 동일한 요소가 연속적으로 나올 때 첫 번째 요소를 제외한 모든 요소를 제거하고, 다시 만들어진 배열의 끝의 iterator를 반환한다. 즉 v{1,2,1,1,3,3,3,4,5,4}; 가 unique를 거치면 {1 2 1 3 4 5 4 x x x} 형태가 되고, 뒤의 x x x 는 불확실하며, 마지막 4를 가리키는 반복자를 반환한다.
auto를 이용하여 자료형을 모르는 상황에서도 적절한 자료형을 리턴할 수 있게끔 했다.
뒤의 불확실한 요소들을 제거하기 위해 earse를 사용했다.

💻소스코드

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

vector<int> solution(vector<int> arr) 
{
    vector<int> answer = arr;
    auto last = unique(answer.begin(), answer.end());
    answer.erase(last, answer.end());
    return answer;
}

📝 제일 작은 수 제거하기

문제 설명

제일 작은 수 제거하기

해결 방법

algorithm 헤더에 있는 min_element() 함수를 사용해서 arr의 최솟값의 iterator를 구한 후 erase() 함수를 사용해서 제거한다. 이 때 answer의 size가 0이면 -1을 push_back 해준다.

💻소스코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> solution(vector<int> arr) {
    vector<int>::iterator min_idx = min_element(arr.begin(), arr.end());
    arr.erase(min_idx);
    vector<int> answer = arr;
    if (answer.size() == 0)
        answer.push_back(-1);
    return answer;
}

📝 K번째 수

문제 설명

K번째 수

해결 방법

이차원 동적 배열 commands 각 행의 0열에 해당하는 값(commands[i][0])부터 1열에 해당하는 값(commands[i][1])까지를 범위로 array 배열을 자른다. 이 때 인덱스는 0부터가 아니라 1부터 시작한다. 범위에 해당하는 값들을 tmp 벡터에 넣어주고 sort 함수를 이용하여 오름차순 정렬한다. 정렬이 완료된 tmp 벡터에서 k번째 수(commands[i][2] - 1)를 answer 벡터에 push_back 하고 이 과정을 commands.size() 만큼 반복한다.

💻소스코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> solution(vector<int> array, vector<vector<int>> commands) {
    vector<int> answer;
    for (int i = 0; i < commands.size(); i++){
        vector<int> tmp;
        for (int j = commands[i][0]; j <= commands[i][1]; j++){
            tmp.push_back(array[j - 1]);   
        }
        sort(tmp.begin(), tmp.end());
        answer.push_back(tmp[commands[i][2] - 1]);
    }
    return answer;
}

📝 모의고사

문제 설명

모의고사

해결 방법

1번 수포자의 찍기 규칙은 1,2,3,4,5 반복
2번 수포자의 찍기 규칙은 2,1,2,3,2,4,2,5 반복
3번 수포자의 찍기 규칙은 3,3,1,1,2,2,4,4,5,5 반복
세 수포자의 찍기 규칙을 각각 num1, 2, 3 배열로 초기화시키고 맞춘 문제 수를 카운팅하는 cnt 배열을 선언하고 초기화한다.
answers의 정답들과 세 수포자의 답들을 각각 비교해서 일치하면 cnt를 증가시킨다.
가장 큰 cnt 값을 max_cnt 변수에 담고, cnt 배열에 max_cnt와 같은 값이 있으면 answer 배열에 인덱스 위치를 push_back 한다.
1번 수포자부터 순서대로 비교하고 넣으므로 answer 배열의 오름차순 정렬은 자동으로 이루어진다.

💻소스코드

#include <string>
#include <vector>

using namespace std;

vector<int> solution(vector<int> answers) {
    vector<int> answer;
    // 수포자 1, 2, 3의 찍기 규칙
    int num1[5] = {1, 2, 3, 4, 5}, num2[8] = {2, 1, 2, 3, 2, 4, 2, 5}, num3[10] = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
    //  수포자 1, 2, 3의 맞은 문제 수
    int cnt[3] = {0, 0, 0};     
    for (int i = 0; i < answers.size(); i++){
        if (answers[i] == num1[i % 5])
            cnt[0]++;
        if (answers[i] == num2[i % 8])
            cnt[1]++;
        if (answers[i] == num3[i % 10])
            cnt[2]++;
    }
    // 문제를 가장 많이 맞힌 사람
    int max_cnt = max(max(cnt[0], cnt[1]), cnt[2]);
    for (int i = 0; i < 3; i++){
        if (max_cnt == cnt[i])
            answer.push_back(i + 1);
    }
    return answer;
}

📝 완주하지 못한 선수

문제 설명

완주하지 못한 선수

해결 방법

참가자 벡터, 완주자 벡터를 sort 함수를 통해 이름순으로 정렬
처음부터 차례차례 비교해서 같지 않다면 바로 그 참가자를 반환
위 조건에 해당하지 않는다면 완주하지 못한 선수가 참가자 명단의 맨 뒤에 있으므로 참가자 - 1 반환

💻소스코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

string solution(vector<string> participant, vector<string> completion) {
    sort(participant.begin(), participant.end());
    sort(completion.begin(), completion.end());
    for (int i = 0; i < completion.size(); i++){
        if (participant[i] != completion[i])
            return participant[i];
    }
    return participant[participant.size() - 1];
}

📝 체육복

문제 설명

Greedy: 체육복

해결 방법

lost와 reserve를 먼저 정렬해주었다. 여벌 체육복을 가지고 있는 학생이 도난당했을 경우 lost와 reserve 배열에서 모두 지운다. 체육수업을 들을 수 있는 최소 학생 수는 "전체 학생수(n) - 체육복을 도난당한 학생수(lost.size())"이다. 조건을 만족하여(체육복은 바로 앞 번호 또는 바로 뒷 번호 학생에게만 빌릴 수 있다.) 체육수업을 들을 수 있는 학생을 answer에 더한다. lost배열에 문제 조건에 만족하는 학생 번호가 reserve 배열에 있다면 여벌 체육복을 빌리고 해당 번호에 해당하는 학생을 reserve 배열에서 지운다. 더 이상 체육복을 빌려줄 수 있는 학생이 없거나(reserve.size() == 0), 전체 학생이 체육수업을 들을 수 있으면(answer == n) 반복문을 종료하고 후 answer를 return한다.

💻소스코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int solution(int n, vector<int> lost, vector<int> reserve) {
    sort(lost.begin(), lost.end());
    sort(reserve.begin(), reserve.end());
    
    // reserve 배열을 지워나가며 체육수업을 들을 수 있는 학생을 추가
    // 여벌 체육복을 가지고 있는 학생이 도난당했을 경우
    for(int i = 0; i < lost.size(); i++) {
        for(int j = 0 ; j < reserve.size(); j++) {
            if(lost[i] == reserve[j]) {
                lost.erase(lost.begin() + i);
                reserve.erase(reserve.begin() + j);
                i = -1;
                break;
            }
        }
    }
    // 체육수업을 들을 수 있는 최소학생 수
    int answer = n - lost.size();
    
    for (int i = 0; i < lost.size(); i++) {
        // 체육복을 모두 빌려주었거나, 모든 학생이 체육수업을 들을 수 있으면 반복문 종료
        if (answer == n || reserve.size() == 0)
            break;
        // 앞 번호 학생에게 체육복 빌려주기
        if (find(reserve.begin(), reserve.end(), lost[i] + 1) != reserve.end()) {
            answer++;
            reserve.erase(find(reserve.begin(), reserve.end(), lost[i] + 1));
        }
        // 뒷 번호 학생에게 체육복 빌려주기
        if (find(reserve.begin(), reserve.end(), lost[i] - 1) != reserve.end()) {
            answer++;
            reserve.erase(find(reserve.begin(), reserve.end(), lost[i] - 1));
        }
    }
    return answer;
}

profile
알고리즘

0개의 댓글