ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 42883_큰 수 만들기(c++)
    Problem Solving/PROGRAMMERS 2019. 11. 12. 20:40

     

     

    문제 설명

     

    어떤 숫자에서 k개의 수를 제거했을 때 얻을 수 있는 가장 큰 숫자를 구하려 합니다.

    예를 들어, 숫자 1924에서 수 두 개를 제거하면 [19, 12, 14, 92, 94, 24] 를 만들 수 있습니다. 이 중 가장 큰 숫자는 94 입니다.

     

    문자열 형식으로 숫자 number와 제거할 수의 개수 k가 solution 함수의 매개변수로 주어집니다. number에서 k 개의 수를 제거했을 때 만들 수 있는 수 중 가장 큰 숫자를 문자열 형태로 return 하도록 solution 함수를 완성하세요.

     

    제한 조건

    • number는 1자리 이상, 1,000,000자리 이하인 숫자입니다.
    • k는 1 이상 number의 자릿수 미만인 자연수입니다.

     

    입출력 예

    numberkreturn

    1924 2 94
    1231234 3 3234
    4177252841 4 775841

     


     

    #C++ 첫 접근

     

    - 처음 접근은 들어온 수를 오름차순으로 정렬하고 k개의 개수만큼 삭제하면 된다고 생각함.

    - 그래서 sv(sorted vector)를 선언하고 sort()를 실행함. 원소들이 오름차순으로 정렬됨.

    - sv와 nv를 비교하여 일치하는 곳의 숫자를 지우는 방식으로 구현함.

     

     

    
    #include <string>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    
    using namespace std;
    
    string solution(string number, int k) {
        string answer = "";
        vector<char> nv, sv;
        
        for(int i = 0; i < number.length(); i++) {
            nv.push_back(number.at(i));
            sv.push_back(number.at(i));
        }
        
        sort(sv.begin(), sv.end());
        
        for(int i = 0; i < k; i++){
            char dNum = sv[i];
            for(int j = 0; j < nv.size(); j++){
                if(dNum == nv[j]) {
                    nv.erase(nv.begin() + j);
                    break;
                }
            }
        }
        
        for(int i = 0; i < nv.size(); i++) answer += nv[i];
                
        return answer;
    }

     

     실행 결과

     

    테스트 케이스가 일부만 통과됨. 예제를 다시 살펴보고 기존에 들어온 수의 순서가 바뀌면 안된다는 것을 알게 됨.

     

     

    #C++ 두 번째 접근

     

    - number로 넘어온 데이터를 한자리(한개)씩 처리하기로 결정함.

    - 그래서 현재 처리할 데이터와 기존 데이터를 비교하여 삽입, 삭제를 수행하기 위해 스택 자료구조를 사용함.

    - 기존에 삽입된 원소보다 처리할 원소가 크다면 기존 원소를 삭제하고 현재 데이터를 삽입함.

    - 숫자의 맨 앞자리의 숫자가 크면 클 수록 좋기 때문임. 

    - 이때 주의할 점은 삭제 가능한 크기를 담은 k 이상으로 삭제 연산이 일어나면 안되기 때문에 조건으로 걸어줘야 함.

    - 또한, 처리할 데이터가 스택의 top에 있는 원소보다 큰 경우에 삭제를 수행하는데 반복적으로 top의 원소와 대소 비교 연산을 해야함. 

    - 입출력 예제 3 (4177252841) 을 보자. 처음에 스택에는 4가 삽입되고 그 뒤로 1이 push됨. 그리고 7이 들어올 때 1과 비교해서 7이 더 크기 때문에 pop이 수행됨. 데이터 하나 당 loop를 한번만 실행한다면 아래와 같은 순서로 stack 연산이 일어남.

    - 이렇게 될 경우 가장 맨 앞자리의 수가 7이 아닌 4가 되기 때문에 가장 큰 수를 만든다고 할 수 없음.

     

                    2 push 2 pop 8 push
              2 push 2 pop 5 push 5  5 5
            7 push 7 7 7 7 7 7
      1 push 1 pop 7 push 7 7 7 7 7 7 7
    4 push 4 4 4 4 4 4 4 4 4

      [stack 상황]

     

     

    - 따라서, 비교를 수행했을 때 스택에 있는 원소를 삭제하고 계속 top에 있는 원소와 비교하여 삭제를 처리해주어야 함. 그래서 whlie문을 통해 삭제 후에도 top의 원소를 반복적으로 비교할 수 있도록 구현함.

     

                         
                       2 push 2 pop
                2 push 2 pop 5 push 5 5
      1 push 1 pop     7 push 7 7 7 7 7
    4 push 4 4 pop 7 push 7 7 7 7 7 7

      [stack 상황]

     

    - 그리고 k개만큼 삭제를 못한 경우도 있기 때문에 k개와 같아지도록 pop 연산을 수행함.

    - 이것이 가능한 이유는 스택에 들어간 원소는 이전 원소보다 작거나 같다는 의미이기 때문임. 

     

     

    
    #include <string>
    #include <vector>
    #include <stack>
    #include <algorithm>
    
    using namespace std;
    
    string solution(string number, int k) { //큰 수 만들기 - success
        string answer = "";
        int size = number.length() - k;
        stack<char> st;
        
        for(int i = 0; i < number.length(); i++){
            char cur = number.at(i); //처리할 숫자
            while(!st.empty() && k > 0){ //
                char top = st.top(); //스택의 가장 맨 위의 값
                if(top < cur){ //값 비교
                    st.pop(); //처리할 값이 더 크기 때문에 pop 수행
                    k--; //제거 횟수 감소
                }
                else break; //비교할 때 값이 같거나 스택에 있는 값이 더 큰 경우
            } 
            st.push(cur); //처리하는 값이 큰 경우를 제외하고 모든 경우 스택에 삽입
        }
        
        //처리하고 남은 스택의 사이즈와 제거하고 남아야하는 수가 같아야함.
        //아닌 경우 같아질 때까지 제거(스택에 남아있다는 것은 제거할 원소보다 이전 원소가 작거나 같다는 의미이므로)
        while(st.size() != size) st.pop(); 
    
        
        while(!st.empty()){ //결과값 생성
            answer += st.top();
            st.pop();
        }
        
        //위에서 거꾸로 값이 이어졌기 때문에 reverse 수행
        reverse(answer.begin(), answer.end()); 
        
        return answer;
    }

     

     

    실행 결과

     

Designed by Tistory.