TOP

with code & food

문제 내용

 

문제 설명

스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.

예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.

 

종류 이름
얼굴 동그란 안경, 검정 선글라스
상의 파란색 티셔츠
하의 청바지
겉옷 긴 코트

 

스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

제한사항

  • clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.

  • 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.

  • 같은 이름을 가진 의상은 존재하지 않습니다.

  • clothes의 모든 원소는 문자열로 이루어져 있습니다.

  • 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.

  • 스파이는 하루에 최소 한 개의 의상은 입습니다.

입출력 예

clothes return
[[yellow_hat, headgear], [blue_sunglasses, eyewear], [green_turban, headgear]] 5
[[crow_mask, face], [blue_sunglasses, face], [smoky_makeup, face]] 3

 

나의 생각

 

1. 어떻게 풀까? 

부위 별 옷의 개수를 정리합니다.

 

answer : 반환할 변수

m : 옷의 종류를 key값으로 개수를 카운팅 할 변수 

 

#include <unordered_map>

int solution(vector<vector<string>> clothes){
    int answer = 1;
    unordered_map <string, int> m;
    
    for(int i = 0; i < clothes.size(); ++i){
    	m[clothes[i][1]]++;
    }
}

 

2. 종류 별로 정리했으면 경우의 수를 어떻게 구할까?

만약 3가지의 옷의 종류(얼굴, 상의, 하의)가 있다면 그 3가지 옷으로 입을 수 있는 경우의 수를 구하는 방법은

 아래와 같을 것입니다.

 

(얼굴 옷의 개수) x (상의 옷의 개수) 개수) x (하의 옷의 개수) 

 

하지만 이번 문제는 각각의 종류의 옷을 안 입는 경우도 포함되어 있습니다. 

그렇다면 각 옷의 개수에  1 (옷을 입지 않는 경우)을/를 더해줍니다.

 

(얼굴 옷의 개수 + 1) x (상의 옷의 개수 + 1) x (하의 옷의 개수 + 1)

 

그 결과 세 종류의 옷을 다 안 입는 경우도 그 값에 포함되어 결괏값이 나옵니다.

즉, 아예 안 입는 경우를 저 식에서 빼줍니다.

 

((얼굴 옷의 개수 + 1) x (상의 옷의 개수 + 1) x (하의 옷의 개수 + 1)) - 1

 

int solution(vector<vector<string>> clothes){
    ...
    for(auto & pair : m)
    	answer *= (pair.second +1);
    return answer - 1; 
}

 

전체 코드

 

#include <string>
#include <vector>
#include <unordered_map>
using namespace std;

int solution(vector<vector<string>> clothes) {
    int answer = 1;
    
    unordered_map <string, int> m;
    
    for(int i = 0; i < clothes.size(); ++i){
        m[clothes[i][1]]++;
    }
    
    for(auto & pair : m){
        answer *= (pair.second + 1);   
    }
    return answer-1;
}

 

테스트 코드 (필요하신 분만)

 

int main(){
	const vector<vector<vector<string>>> testcases = {
        {
            {"yellow_hat", "headgear"}, 
            {"blue_sunglasses", "eyewear"}, 
            {"green_turban", "headgear"}
        },
        {
            {"crow_mask", "face"}, 
            {"blue_sunglasses", "face"}, 
            {"smoky_makeup", "face"}
        }
    };
    
    for(auto & testcase : testcases){
       const int ret = solution(testcase);
       cout << ret << endl;
    }
    return 0;
}

 

힙 이란?

 

완전 이진트리로 구현되어 있으며 속성에 따라 부모 노드에 큰 값, 작은 값 둘 중 하나가 올 수 있습니다.

최대 힙 : 자식 노드보다 부모 노드의 값이 힙을 뜻 합니다.

최소 힙 : 자식 노드보다 부모 노드의 값이 작은 힙을 뜻 합니다.

 

힙은 반환 시 최대 값 또는 최소 값을 반환합니다.

즉 위의 트리에서 루트 노드(최상위 노드)가 반환 후 재 정렬하여 루트 노드에 최대 값 또는 최소 값을 배치시킵니다.

 

구현 (최대 힙) - 배열

1. PUSH()

데이터를 힙에 저장하는 작업입니다.

트리를 배열로 생각해 봅니다. 

완전 이진트리는 부모 노드 아래에 자식 노드 두 개가 있는 구조입니다.

즉, 자식 / 2의 값이 부모 노드의 인덱스가 됩니다.

 

void push(int data){
    heap[++index] = data;
    
    int child = index;
    int parent = child / 2;
    ...
}

 

데이터를 저장하기만 하고 끝내면 힙이 되지 않습니다.

최대 힙을 구현하는 것이기 때문에 들어온 값과 상위 노드 값들과 비교하며 정렬을 해줍니다.

정렬 방식은 부모 노드와 자식 노드를 비교하여 자식 노드가 더 클 시 자리를 바꿔주는 작업을 반복하며 루트 노드까지 반복하여 비교해갑니다.

 

void push(int data){
    ...
    while(child > 1 && heap[child] > heap[parent]){
    	swap(heap[parent], heap[child]);
        
        // 노드를 타고 올라간다.
        child = parent;
        parent = child / 2;
    }
}

 

2. POP()

데이터를 꺼내는 작업입니다. (루트 노드 출력)

루트 노드 값을 지우는 방법은 루트 노드 값과 Index에 위치한 값과 자리를 변경합니다.

그 후 index에 값을 0으로 변경합니다.

 

int pop(){
   // 루트 노드값 저장
   int ret = heap[1];
   
   // 루트 노드 값 삭제
   swap(heap[1], heap[index]);
   heap[index] = 0;
   --index;
   
   ...
   
   return ret;
}

 

pop() 작업도 push() 작업과 동일하게 재 정렬을 해서 루트 노드에 최대 값이 오도록 해줍니다.

여기서 생각해봐야 할 것은 자식 노드는 두 개입니다. 

그렇다면 자식 노드가 두 개인 경우 자식 노드 안의 값이 더 큰 쪽으로 child 값을 지정해 줍니다.

어느 자식의 길로 갈지 정해준다 생각하면 됩니다.

 

int pop(){
    ...
    
    int parent = 1;
    int child = parent * 2;
    
    // 자식 노드가 2개 라면 (child : 첫번째 자식, child + 1 : 두번째 자식)
    if(child + 1 <= index)
    	child = heap[child] > heap[child + 1] ? child : child + 1;
    ...
}

 

어느 자식 쪽으로 갈지 정했으면 현재 값이 들어있는 노드(index)까지 부모와 자식을 비교해서 자식이 크면 부모 위치로 변경해주는 작업을 반복해줍니다.

 

int pop(){
    ...
    
    while(child <= index && heap[parent] < heap[child]){
        swap(heap[parent], heap[child]);
        
        parent = child;
        child = parent * 2;
        if(child + 1 <= index)
            child = heap[child] > heap[child + 1] ? child : child + 1;
    }
    ...
}

 

전체 코드

 

#include <iostream>

#define MAX_SIZE 256

using namespace std;

int heap[MAX_SIZE];
int index = 0;

void swap(int & a, int & b){
    int tmp = a;
    a = b;
    b = tmp;
}

void push(int data){
    heap[++index] = data; 
    
    int child = index;
    int parent = child / 2; 

    while(child > 1 && heap[parent] < heap[child]){
        swap(heap[parent], heap[child]);
        child = parent;
        parent = child / 2;
    }
}

int pop(){
    int ret = heap[1];

    swap(heap[1], heap[index]);
    heap[index--] = 0;
    
    int parent = 1;
    int child = parent * 2;
    if(child + 1 <= index){
        child = (heap[child] > heap[child + 1]) ? child : child + 1;
    }

    while(child <= index && heap[parent] < heap[child]){
        swap(heap[parent], heap[child]);

        parent = child;
        child = parent * 2; 
        if(child + 1 <= index){
            child = (heap[child] > heap[child + 1]) ? child : child + 1;
        }
    }
    return ret;
}

 

테스트 코드 (필요하신 분만)

 

1 : push() 작업

2 : pop() 작업

3 : 현재 배열 안에 상태를 확인할 수 있습니다.

 

int main()
{

    while (true)
    {
        int choice = 0;
        int push_data = 0;
        cout << "input : ";
        cin >> choice;

        switch (choice)
        {
        case 1:
            cout << "push : ";
            cin >> push_data;
            push(push_data);
            break;
        case 2:
            cout << pop() << endl;
            break;
        case 3:
            for (int i = 1; i < MAX_HEAP_SIZE; ++i)
            {
                if (heap[i] == 0)
                    break;
                cout << heap[i] << ", ";
            }
            cout << endl;
            cout << "================================" << endl;
            break;
        default:
            return 0;
        }
    }

    return 0;
}

 

'알고리즘' 카테고리의 다른 글

트라이 알고리즘이란 ? (feat.cpp)  (0) 2020.11.03
[프로그래머스] 위장  (0) 2020.11.02
[프로그래머스] 가장 큰 수  (0) 2020.10.30
[프로그래머스] 괄호 변환  (0) 2020.10.29
[프로그래머스] 소수 찾기  (0) 2020.10.28

수플레를 먹고 싶어 찾게 된 카페 

Near And Dear

1층에 아담하고 노랗게 자리 잡고 있는 전체적으로 이쁜 가게예요

가게 앞에는 주차를 할 수 있는 거 같더라고요

(전 차가 없어서.. 대중교통 타고 갔지만..)

 

가게 안으로 입장했을 때 실내 디자인은

전체적으로 화이트 색상에 심플해서 그런지

답답한 느낌보다는 편안한 느낌이에요

 

아! 그리고 잔잔한 노래도 틀어주셔서 그런지

더 편안하게 느껴진 거 같아요!

 

(사진은 문에서 좌 / 우입니다.)

입장 후 주문할 때 수플레와 음료를 같이 시키면

"음료 먼저 드릴 가요?"라고 물어보시는데...

 

역시 둘이 같이 먹어야 제 맛이죠!

 

그리고 여기는 직접 가져다주신답니다!

마스크도 물론 하고 계셔요!

(서비스 너무 좋아요)

 

저희가 시킨 메뉴는

계절과일 수플레와

레몬 에이드 그리고 아이스 아메리카노 에요

 

그리고

계절 과일로는

청포도 포도 무화과 바나나 멜론 키위 오렌지

알차게 나왔어요!!

(다른 계절도 궁금해지는군요.. 츄릅)

수플레는 메이플 시럽과 생크림이 같이 나왔어요!

전 메이플 시럽이 뭔지 몰라서...

당당하게 물어봤지요!

 

수플레를 메이플 시럽을 뿌린 뒤 생크림을 찍어 먹으면

입안에서 부드러운 맛이 한 층 더해져요~

그리고 무엇보다 중요한 것은 칼로리도 한 층...

 

운동할 겁니다.

 

참고로 메이플 시럽만 찍어서 먹어도 보고

그냥도 먹어 봤는데 부드러운 식감이

그때그때마다 다르더라고요...

그래도 어떻게 먹든 맛있었어요!

 

맛있으면 역시 싹싹 비워 먹어야지요~

잘 먹었습니다~

(점심 먹고 간 거지만... 순식간...)

 

가보실 분들을 위해 간단한 오픈 시간과 지도 알려드리고

이만 전 가보겠습니다~

 

 

문제 내용

문제 설명

0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.

예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.

0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • numbers의 길이는 1 이상 100,000 이하입니다.
  • numbers의 원소는 0 이상 1,000 이하입니다.
  • 정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.

입출력 예

numbers return
[6, 10, 2] "6210"
[3, 30, 34, 5, 9] "9534330"

 

나의 생각

1. 어떻게 풀까?

그리디 알고리즘을 사용합니다.

 

여기서 잠깐!! 그리디 알고리즘이란?

욕심쟁이 알고리즘으로 제일 큰 것부터 우선으로 택하는 알고리즘을 말합니다.

 

2. 그리디 알고리즘이 잘 작동할 것인가? 

그냥 큰 수 순서대로 정렬을 숫자를 만들게 될 시 제대로 된 답이 나오지 않습니다.

위의 케이스를 예를 들어 6, 10이라는 숫자를 큰 순서대로 놓을 시 106(10, 6)이라는 숫자가 됩니다.

하지만 610(6, 10)이라는 순서가 더 큰 숫자이지요.

그러므로 저희는 두 문자열을 순서대로 합친 것과, 반대로 합친 것 중에 큰 수를 택해주면 되는 것입니다.

bool compare_big_number(int a, int b){

    const string A = to_string(a);
    const string B = to_string(b);
    // 순서대로 합 친 수와 반대로 합 친 수 비교
    return A + B > B + A;
}

위 함수를 sort() 함수와 같이 사용하면 위 함수의 결과를 토대로 정렬이 완성됩니다.

string solution(vector<int> numbers){
    ...
    sort(numbers.begin(), numbers.end(), compare_big_number);
    ...
}

 

3. 예외는 존재하지 않을까?

이제 정렬도 되었으니 순서대로 이어 붙이면 가장 큰 수가 완성이 됩니다.

하지만 예외가 존재합니다. 

만약에 {0, 0, 0} 테스트 케이스가 온다면 결괏값은 000이라는 값이 출력될 것입니다.

그러므로 아래 식을 통하여 예외를 처리해줍니다.

string solution(vector<int> numbers){
    ...
    // 만약 처음 숫자가 0 일 경우
    if(numbers.at(0) == 0) return "0";
    ...
}

(0이 제일 처음 나오면서 큰 수 일 경우는 0으로만 이루어진 테스트 케이스 바께 없습니다.)

 

전체 코드

 

bool compare_sum_number(int a, int b){
    const string A = to_string(a);
    const string B = to_string(b);
    
    return A + B > B + A;
}

string solution(vector<int> numbers) {
    string answer = "";
    
    sort(numbers.begin(), numbers.end(), compare_sum_number);
    if(numbers.at(0) == 0) return "0";
    for(auto number : numbers)
        answer += to_string(number);
    return answer;
}

 

 

테스트 코드 (필요하신 분만)

 

int main(){int main(){
    const vector<vector<int>> numbers_testcases = { 
        {6, 10, 2},
        {3, 30, 34, 5, 9},
        {0, 0}
    };

    for(auto numbers : numbers_testcases){
        const string ret = solution(numbers);
        cout << ret << endl;
    }
    return 0;
}

'알고리즘' 카테고리의 다른 글

[프로그래머스] 위장  (0) 2020.11.02
[heap] 힙 이란? (feat.cpp)  (0) 2020.11.01
[프로그래머스] 괄호 변환  (0) 2020.10.29
[프로그래머스] 소수 찾기  (0) 2020.10.28
에라토스테네스의 체란? (feat.cpp 구현)  (0) 2020.10.28

 

문제 내용

문제 설명

카카오에 신입 개발자로 입사한 은 선배 개발자로부터 개발 역량 강화를 위해 다른 개발자가 작성한 소스 코드를 분석하여 문제점을 발견하고 수정하라는 업무 과제를 받았습니다. 소스를 컴파일하여 로그를 보니 대부분 소스 코드 내 작성된 괄호가 개수는 맞지만 짝이 맞지 않은 형태로 작성되어 오류가 나는 것을 알게 되었습니다.
수정해야 할 소스 파일이 너무 많아서 고민하던 콘은 소스 코드에 작성된 모든 괄호를 뽑아서 올바른 순서대로 배치된 괄호 문자열을 알려주는 프로그램을 다음과 같이 개발하려고 합니다.

 

용어의 정의

'('와')' 로만 이루어진 문자열이 있을 경우, '('의 개수와 ')'의 개수가 같다면 이를 균형 잡힌 괄호 문자열이라고 부릅니다.
그리고 여기에 '('와 ')'의 괄호의 짝도 모두 맞을 경우에는 이를 올바른 괄호 문자열이라고 부릅니다.
예를 들어, "(()))("와 같은 문자열은 균형 잡힌 괄호 문자열이지만 올바른 괄호 문자열은 아닙니다.
반면에 "(())()"와 같은 문자열은 균형 잡힌 괄호 문자열 이면서 동시에 올바른 괄호 문자열입니다.

'('와 ')' 로만 이루어진 문자열 w가 균형 잡힌 괄호 문자열이라면 다음과 같은 과정을 통해 올바른 괄호 문자열로 변환할 수 있습니다.

 

ex)

1. 입력이 빈 문자열인 경우, 빈 문자열을 반환합니다.

2. 문자열 w를 두 "균형 잡힌 괄호 문자열" u, v로 분리합니다. 단, u는 "균형 잡힌 괄호 문자열"로 더 이상 분리할 수 없어야 하며, v는 빈 문자열이 될 수 있습니다.

3. 문자열 u가 "올바른 괄호 문자열"이라면 문자열 v에 대해 1단계부터 다시 수행합니다.

    3-1. 수행한 결과 문자열을 u에 이어 붙인 후 반환합니다.

4. 문자열 u가 "올바른 괄호 문자열"이 아니라면 아래 과정을 수행합니다.

    4-1. 빈 문자열에 첫 번째 문자로 '('를 붙입니다.

    4-2. 문자열 v에 대해 1단계부터 재귀적으로 수행한 결과 문자열을 이어 붙입니다.

    4-3. ')'를 다시 붙입니다.

    4-4. u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다. 4-5. 생성된 문자 열을 반환합니다.

 

입출력 예

p result
"(()())()" "(()())()"
")(" "()"
"()))((()" "()(())()"

 

나의 생각

1. 어떻게 풀까?

예시로 주어진 내용 그대로 프로그램을 제작해봅니다.

노란색 밑줄을 조건으로 분기가 일어납니다.("올바른 괄호 문자열" 인지 검사)

올바른 문자열인지 판별

bool checked_bracket(string p){
    stack <char> st;
    const int p_size = p.size();
    
    for(int i = 0; i < p_size; ++i){
        if(p.substr(i, 1) == ")"){
            if(st.empty()) return false;
            st.pop();
        }else{
            st.push(p[i]);
        }
    }
    if(!st.empty()) return false;
    return true;
}

 

2. 이것을 이용해서 어떤 식으로 문제를 풀까?

문자열 u가 "올바른 괄호 문자열"이라면 문자열 v에 대해 1단계부터 다시 수행합니다.

이 글을 위 함수에 대입해서 얘기하자면  checked_bracket(u) 함수 결과가 true 면 문자열 v로 처음부터 시작합니다.

즉, u는 올바른 문자열이기 때문에 그대로 붙여주고 v에 대해서만 처음부터 검사를 시작합니다.

string solution(string p){
	...
    if(checked_bracket(u)){
    	answer += u;
    	return answer += solution(v);
    }
    ...
}

 

또 다른 조건, 문자열 u가 "올바른 괄호 문자열"이 아니라면 아래 과정을 수행합니다.

이 조건도 대입해서 바꿔준다면 위의 조건의 else 문이 됩니다.

 

3. 그러면 else문 내용은?

먼가 길게 적혀있어서 어렵게 느껴졌던 부분이 있습니다.

하지만 잘 읽어보면 전체적인 내용은 이와 같습니다.

1. u의 첫 번째 마지막 문자 제거

2. 제거된 문자열 뒤집기

3. "(" + solution(v) + ")" + 제거된 문자열

 

string solution(string p){
	...
    else{
  		// u의 앞, 뒤 문자열 제거
        string word = u.substr(1, u.size() - 2);
        // 제거 된 문자열 뒤집기.
        for(int i = 0; i < word.size(); ++i){
            if(word.substr(i, 1) == ")"){
                word.replace(i, 1, "(");
            }else{
                word.replace(i, 1, ")");
            }
        }
        
        return answer += "(" + solution(v) + ")" + word;
    }
    ...
}

전체 코드

 

#include <string>
#include <vector>
#include <stack>
using namespace std;
bool checked_bracket(string p){
    stack <char> st;
    const int p_size = p.size();
    
    for(int i = 0; i < p_size; ++i){
        if(p.substr(i, 1) == ")"){
            if(st.empty()) return false;
            st.pop();
        }else{
            st.push(p[i]);
        }
    }
    if(!st.empty()) return false;
    return true;
}
string solution(string p) {
    if(checked_bracket(p)) return p;
    string answer = "";
    string u = "", v = "";
    int left = 0, right = 0;
    const int p_size = p.size();
    
    // 좌우 문자열이 균형잡힌 문자열인 경우 breakl
    for(int i = 0; i < p_size; ++i){
        if(p.substr(i , 1) == ")"){
            ++left;
        }else{
            ++right;
        }
        u += p.substr(i, 1);
        if(left == right){
            v += p.substr(i + 1);
            break;
        }
    }
    
    if(checked_bracket(u)){
        answer += u;
        return answer += solution(v);
    }else{
        string word = u.substr(1, u.size() - 2);
        
        for(int i = 0; i < word.size(); ++i){
            if(word.substr(i, 1) == ")"){
                word.replace(i, 1, "(");
            }else{
                word.replace(i, 1, ")");
            }
        }
        return answer += "(" + solution(v) + ")" + word;
    }
    
    return answer;
}

 

테스트 코드 (필요하신 분만)

 

int main(){
    vector <string> p_cases = {
        "(()())()", ")(", "()))((()"
    };

    for(int i = 0; i < p_cases.size(); ++i){
        const string ret = solution(p_cases[i]);
        cout << ret << endl;
    }
    return 0;   
}

'알고리즘' 카테고리의 다른 글

[프로그래머스] 위장  (0) 2020.11.02
[heap] 힙 이란? (feat.cpp)  (0) 2020.11.01
[프로그래머스] 가장 큰 수  (0) 2020.10.30
[프로그래머스] 소수 찾기  (0) 2020.10.28
에라토스테네스의 체란? (feat.cpp 구현)  (0) 2020.10.28





문제 내용

한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.

각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.

제한사항

  • numbers는 길이 1 이상 7 이하인 문자열입니다.
  • numbers는 0~9까지 숫자만으로 이루어져 있습니다.
  • 013은 0, 1, 3 숫자가 적힌 종이 조각이 흩어져있다는 의미입니다.

입출력 예

numbers return
17 3
011 2


나의 생각

1. 소수를 구하는 방법? 에라토스테네스의 체를 이용합니다.

에라토스테네스의 체에 관하여 궁금하신 분은 아래 링크를 확인하고 오시면 감사하겠습니다.

에라토스테네스의 체란? (feat.cpp 구현)
소수 란? 1과 자기 자신을 제외한 나누어지는 수가 없는 수를 말합니다. 그렇게 되면 2를 제외한 모든 짝수는 소수가 될 수 없습니다. (짝수들은 2로 나누어 떨어지기 때문입니다.) bool check_the_prime_number(i..
coderb.tistory.com


2. 어느 숫자까지의 소수를 구해야 할까? 문자열로 만들 수 있는 최댓값까지 구합니다.(sort)

void solution(string numbers){
    // numbers 문자열 최댓값으로 만들기
    sort(numbers.begin(), numbers().end(), greater<int> ());
}

3. 문자열 조합은 어떻게 만들어 낼가? next_permutation()을 사용한다.


4. 중복되는 값은 어떻게 처리할까? set()을 사용하여 저장한다(set은 중복된 값을 허용하지 않는다.)

set <int> prime_tree;
sort(numbers.begin(), numbers.end());

do{
    for(int i = 1; i <= numbers.size(); ++i){
        string tmp = numbers.substr(0, i);
        if(!prime_number[stoi(tmp)])
            prime_tree.insert(stoi(tmp));
    }
}while(next_permutation(numbers.begin(), numbers.end()));



전체 코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;

// 에라토스테네스의 체 알고리즘
void eratothenes(vector <bool> & prime_numbers){
    prime_numbers[0] = true;
    prime_numbers[1] = true;

    for(int i = 2; i < sqrt(prime_numbers.size()); ++i){
        if(!prime_numbers[i]){
            for(int j = i * 2; j < prime_numbers.size(); j+=i){
                prime_numbers[j] = true;
            }
        }
    }
}

int solution(string numbers){
    int answer = 0;
    // 큰수 만들기
    sort(numbers.begin(), numbers.end(), greater<int>());
    vector <bool> prime_numbers(stoi(numbers) + 1, false);
    eratothenes(prime_numbers);

    set <int> prime_tree;

    sort(numbers.begin(), numbers.end());
    do{
        for(int i = 1; i <= numbers.size(); ++i){
            string tmp = numbers.substr(0, i);
            if(!prime_numbers[stoi(tmp)])
                prime_tree.insert(stoi(tmp));
        }
    }while(next_permutation(numbers.begin(), numbers.end()));

    answer = prime_tree.size();
    return answer;
}

테스트 코드(필요하신분 만)


int main()
{
    const vector<string> numbers_testcases = {"17", "011"};

    for (int i = 0; i < numbers_testcases.size(); ++i)
    {
        const int ret = solution(numbers_testcases[i]);
        cout << ret << endl;
    }
    return 0;
}


'알고리즘' 카테고리의 다른 글

[프로그래머스] 위장  (0) 2020.11.02
[heap] 힙 이란? (feat.cpp)  (0) 2020.11.01
[프로그래머스] 가장 큰 수  (0) 2020.10.30
[프로그래머스] 괄호 변환  (0) 2020.10.29
에라토스테네스의 체란? (feat.cpp 구현)  (0) 2020.10.28

소수 란?

 

1과 자기 자신을 제외한 나누어지는 수가 없는 수를 말합니다.

그렇게 되면 2를 제외한 모든 짝수는 소수가 될 수 없습니다.

(짝수들은 2로 나누어 떨어지기 때문입니다.)

 

bool check_the_prime_number(int num){
	// 1, 2를 제외한 모든 짝수는 소수가 아니다.(false 반환)
    if(num == 2) return true;
    if(num == 1) return false;
    if(num % 2 == 2) return false;
    
    // n-1의 수까지 나누어 보고 나누어 떨어질시 소수 아님 판정(false)
    for(int i = 3; i < num; ++i){
    	if(num % i == 0) return false;
    }
    
    return true;
}

 

에라토스테네스의 체

 

위의 방식에서 효율적으로 소수를 찾는 방법이 에라토스테네스 체의 방법입니다.

n이라는 숫자 안에 소수가 무엇이 존재하는지 알고 싶은 경우

2... n까지의 숫자를 종이에 적은 후 자기 자신을 제외한 배수들을 하나씩 지웁니다.

 

1. 2를 제외한 2의 배수들을 지워줍니다.

2를 제외한 2의 배수를 지운모습

2. 다음 수중 지워지지 않은 수(3)의 배수들을 지워줍니다.

3을 제외한 3의 배수들을 지운 모습

1, 2의 과정을 n번째까지 진행합니다.

 

결과적으로 남은 수들은 소수가 됩니다.

#include<vector>
#include<cmath>
using namespace std;

vector<bool> solution(int n){
	// n + 1만큼의 bool 배열 (소수인지 아닌지 체크용)
	// false : 소수 / true : 소수가 아님
    vector<bool> checked(n + 1, false);
    
    checked[0] = true;
    checked[1] = true;
    
    for(int i = 2; i < sqrt(n); ++i){
    	if(!checked[i]){
        	// 소수가 아닐경우 
            // i의 배수인 수들을 지워준다(true)
            for(int j = i * 2; j < n; j+=i){
            	checked[j] = true;
            }
        }
    }
    
    return checked;
}

 

 

 

 

'알고리즘' 카테고리의 다른 글

[프로그래머스] 위장  (0) 2020.11.02
[heap] 힙 이란? (feat.cpp)  (0) 2020.11.01
[프로그래머스] 가장 큰 수  (0) 2020.10.30
[프로그래머스] 괄호 변환  (0) 2020.10.29
[프로그래머스] 소수 찾기  (0) 2020.10.28