프로그래밍 공부
작성일
2024. 2. 5. 15:36
작성자
WDmil
728x90

문제 설명

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


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


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

 

제한 조건

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

 

입출력 예

number  K return
"1924" 2 "94"
"1231234" 3 "3234"
"4177252841" 4 "775841"

문제 해설

 

가장 큰 수의 조건을 생각하자.

가장 큰 수는 모든 객체를 뺐을 때, 좌측값이 가장 커야함을 기억해야 한다.

 

number는 2자리 이상, 1,000,000자리 이하인 숫자 라는 것은, int나 double같은 데이터형 숫자가 아닌, string형태의 데이터 임을 기억하자. 

 

백만자리 수 까지 계산해야한다는 뜻 이다. 숫자의 최대값이 9,999,999가 아니라, string의 길이가 최대 1,000,000까지 있다는 뜻이다.

 

이해하기 쉽게 쓴다면, 

  • number는 2자리 이상, 1,000,000자리 이하인 숫자입니다.

가 아니라

  • number는 2자리 이상, 1,000,000자리 이하인 문자열입니다.

라고 써야 맞다. 이 프로그래머 공과생들 국어교육좀 다시해야한다.


첫 시도

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

using namespace std;
string answerstring;

void insertnum(string number, int k, int target ,int nownum = 0)
{
    int count = nownum + 1;
    if(count > k)
        return;
    
    for(int i = 0; i < number.size(); i++) {
        string newnumber = number;
        newnumber.erase(i, 1);
        
        if(newnumber.size() == target) {
            if(stoi(answerstring) < stoi(newnumber))
                answerstring = newnumber;
        }
        insertnum(newnumber, k, target, count);
    }
}

string solution(string number, int k) {
    answerstring = "0";
    insertnum(number, k, number.size() - k);
    
    return answerstring;
}

실패

 

모든 테스트는 다 통과하나, 좀더 효율적으로 짜라고 빠꾸먹인 느낌이다.

 

그냥, 모든 객체를 다 돌려보면서, 내가 원하는 사이즈가 나왔을 때 전체비교연산을 통해 비교를 하고, 큰 숫자일 경우에만 대입되도록 바꾸었는데. 실행은 되나 효율적이지 않은느낌?


두 번째 시도

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

using namespace std;
set<string> answerstring;

void insertnum(string number, int k, int target ,int nownum = 0)
{
    int count = nownum + 1;
    if(count > k)
        return;
    
    for(int i = 0; i < number.size(); i++) {
        string newnumber = number;
        newnumber.erase(i, 1);
        
        if(newnumber.size() == target)
            answerstring.insert(newnumber);
        
        insertnum(newnumber, k, target, count);
    }
}

string solution(string number, int k) {
    insertnum(number, k, number.size() - k);
    
    return *answerstring.rbegin();
}

실패

효율문제가 아니라 문항 제한조건이 이상하게 써져있었다.

 

제한조건에서 2이상 1,000,000자리 숫자가, 최대값이 7자리가 아니라 최대값이 백만자리의 숫자라는 의미였음.

그래서 고쳤는데, 시간초과로 실패


세 번째 시도

#include <string>
#include <vector>

using namespace std;

string solution(string number, int k) {
    string answer = number;
    while(k > 0) {
        int nowsize = answer.size();
        for(int i = 0; i < answer.size(); i++)
        {
            if(answer[i] < answer[i+1]) {
                answer.erase(i, 1);
                k--;
                i--;
                break;
            }
            if(k <= 0)
                break;
        }
        
        if(nowsize == answer.size()) {
            answer.erase(answer.size() - 1, 1);
            k--;
        }
    }
    return answer;
}

성공

 

개념자체를 바꿔봤음,

데이터를 전부 넣는것 이 아니라, 조건을 생각해서

가장 왼쪽에 있는 값이 가장 작으면 안된다. 라고 생각. 이걸 뒤집으면 나보다 오른쪽값이 크다면, 나 자신을 빼버리면 됨.

빼버린 다음에 for문 회전에서 한개가 줄었음으로 i를 한개 빼주고, 한개를 뺐음으로 k를 한개 빼줌.

그렇게 해서, for문을 처음부터 다시 돌릴 수 있게 함.

 

만약, 한개도 빼지 못헀다면, 왼쪽의 모든값은 오른쪽 값보다 크다는 의미 임으로, 가장 작은값은 가장 우측의 값임을 알 수 있음.

 

이 예외처리를, size로 확인하고, 해당 size와 시작size가 같다면, 하나도 못뺐다는 의미 임으로, 맨 뒤 값을 한개 빼주면됨.

728x90

'코딩테스트 문제 풀이 > 탐욕법' 카테고리의 다른 글

단속 카메라  (0) 2024.02.20
섬 연결하기  (0) 2024.02.15
구명 보트  (0) 2024.02.15
조이스틱  (0) 2024.01.24
체육복  (0) 2024.01.13