• 큰 수 만들기
  • darklight

    sublimevimemacs

    C++ 

문제 설명

어떤 숫자에서 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

 

풀이 ) 맨처음에는 정렬 하면 되지않나 싶었는데 

예제 3 .을 보면 글자의 순서는 바뀌지 않다는것 1429 엿다고 94가 최고숫자가 아님 429 이면 49가 제일 큰숫자라는게 있었다.

그래서 while 문 조건(범위,중복)만 잘맞춰주면 완성되는 문제 인거같다고 생각하게 되었다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 
int main()
{
    string number = "4177252841";
    int k = 4;
    
    //글자의 순서는 바뀌지 않음
    //1429 엿다고 94가 최고숫자가 아님
    //1429 이면 49가 제일 큰숫자
 
    int Itemp =0;
    
    
    
    int Nsize = number.size() - k;
    int index = 0;
    string answer = "";
    int cylcle = 0;
    while (answer.size() !=Nsize)
    {
        index = 0;
        Itemp = 0;
        if (cylcle == 0)
        {
            for (int i = 0; i < number.size() - Nsize + 1; i++//k개의 숫자를 잘라서 만드는게 길이이고 0부터 시작하므로 +1까지
            {
                if (Itemp == 0)  //처음이면 0이니까 넣어준다
                {
                    Itemp = number.at(i) - '0';
                    index = i;
                    cout << Itemp << endl;
                }
                else if (Itemp >= number.at(i) - '0'// 더크거나 같으면 앞에꺼를 넣어주고
                {
                    continue;
                }
                else
                {
                    Itemp = number.at(i) - '0';  //i번쨰가 크다면 i숫자를 기억하고 위치기억
                    index = i;
 
                }
            }
        }
 
        
        else
        {
            for (int i = 0+cylcle; i < number.size() +answer.size() -Nsize+1; i++//돌면서 기억한 위치뒤를확인하는데 범위가 넘어가지않게
            {
                cout << number.at(i) << " ";
                if (Itemp == 0)
                {
                    Itemp = number.at(i) - '0';
                    index = i;
                    cout << Itemp << endl;
                }
                else if (Itemp >= number.at(i) - '0')
                {
                    continue;
                }
                else
                {
                    Itemp = number.at(i) - '0';
                    index = i;
 
                }
            }
        }
        answer += number.at(index); //위치기억한곳에 넣어주자
        
        cylcle += index+1 -cylcle; //for문을 위한 위치기억
        cout << index << "번쨰" << Itemp << endl//테스트위함
        
    }
 
 
    cout << answer; //답
 
 
    
    
    
 
    
    
 
    
    
 
 
    return 0;
 
 
}
 
cs

 

 

  • 소수 찾기
  • darklight

    sublimevimemacs

    C++ 

문제 설명

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

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

제한사항

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

입출력 예

numbersreturn

17 3
011 2

입출력 예 설명

예제 #1
[1, 7]으로는 소수 [7, 17, 71]를 만들 수 있습니다.

예제 #2
[0, 1, 1]으로는 소수 [11, 101]를 만들 수 있습니다.

  • 11과 011은 같은 숫자로 취급합니다.

 

 

풀이) 일단 문자열을 정렬해서 제일큰수까지 에라스토테네스의 체를 이용한 소수를 찾아준다

       그뒤에는 저수들을 어떤식으로  17이 주어지면 1,7,17,71을 보내서 찾을수가 있을까 하다가 

next_permutation , prev_permutation  이라는 순열 정렬 함수를 찾게 되어서 풀게되었고

중간에 소수를 찾은뒤 소수에서 만약 17이 주어지면 1 , 7 이 들어가기만해도  2라고 수를 바꾸어준뒤에

그뒤에 sub_str을 이용해서 하나씩 2인지 아닌지 체크해주니 할수있었다.

중간에 signal: segmentation fault (core dumped) 가 뜨는문제가 있었는데  

처음에는 무엇이 벗어나는것일까 하고 for문을 보다가 문제가 없는거같아서.
int number[10000000]; 의 범위를 더크게해주었더니 되었다 

 

  


int number[10000000];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
int main()
{
    string numbers = "25489";
    
    vector<int>ab;
 
    
    int n = 0;
    int nn = 0;
    
    sort(numbers.begin(), numbers.end(),greater<int>() );
 
    nn = stoi(numbers);
 
    int answer = 0;
 
    for (int i = 0; i < numbers.size(); i++)
    {
        ab.push_back(numbers[i] - '0');
    }
 
    for (int i = 2; i <= nn; i++)
    {
        if (number[i] == 1)
        {
            continue;
        }
        for (int j = i * 2; j <= nn; j += i)
        {
            number[j] = 1;
        }
 
    }
 
    
 
    for (int i = 2; i <= nn; i++)
    {
        if (number[i] == 0)
        {
            int temp = i;
            
            while (temp !=0)
            {
 
                for (int j = 0; j < ab.size(); j++)
                {
                    if (temp == ab.at(j))
                    {
                        number[i] = 2//하나라도 들어가있으면 체크
                        
                    }
                    
                }
 
                temp /= 10;
            }
            
        }
 
    }
 
 
    do {
        for (int j = 0; j <= ab.size(); j++)
        {
            string temp;
            int b=0;
            
            temp = numbers.substr(0, j + 1);
            
            
            if (number[b] == 2)
            {
 
 
                answer += 1;
                number[b] = 0;
 
            }
 
 
        }
                for (int j = 0; j <= ab.size(); j++)
                {
                    string temp = numbers.substr(0, j+1);
                    int b = stoi(temp);
 
                    if (number[b] == 2)
                    {
                        
                            
                            answer += 1;
                            number[b] = 0;
                            
                    }
 
 
                }
 
 
 
            
 
        
    }
    while (prev_permutation(numbers.begin(), numbers.end()));
 
    
 
    
    
 
 
    return 0;
 
 
}
cs

 

 

  • 최대공약수와 최소공배수
  • darklight

    sublimevimemacs

    C++ 

문제 설명

두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3, 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.

제한 사항

  • 두 수는 1이상 1000000이하의 자연수입니다.

입출력 예

nmreturn

3 12 [3, 12]
2 5 [1, 10]

입출력 예 설명

입출력 예 #1
위의 설명과 같습니다.

입출력 예 #2
자연수 2와 5의 최대공약수는 1, 최소공배수는 10이므로 [1, 10]을 리턴해야 합니다.

 

 

풀이) 최대 공약수는 약수를 찾는데 가장큰 겹치는 수를  리턴한다

3 = 1 3;

12 = 1 2 3 4  6 12;

-> 1 -> 3  3리턴

 

최소 공배수는 풀이가 생각이 나지않아서 두수의 배수를 비교해서 같아지는 수를 리턴해주었다.

 

이보다 최소공배수를 구하는것에 더쉬운것이 있을거같긴한데   

어마어마한큰수를 만약 구한다면 다른 방법을 생각해야할듯싶다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
 
int main()
{
    int n = 60;
    int m =48 ;
    int nn =n;
    int mm =m;
    //1, 2
    //1 ,5
    
 
 
    vector<int>answer;
    
    vector<int>a;
    
 
    while (true)
    {
        for (int i = 1; i <= m; i++)
        {
            if (m % i == 0)
            {
                a.push_back(i);
            
            }
            
 
        }
        
        for (int i = 1;i <= n; i++)
        {
            if (n%i == 0)
            {
                a.push_back(i);
            
            }
        }
 
        break;
 
 
    }
 
 
    sort(a.begin() ,a.end());
    int lower = 0;
    for (int i = 0; i < a.size(); i++)
    {
        if (i + 1 < a.size())
        {
            if (a.at(i) == a.at(i + 1))
            {
                lower = a.at(i);
                a.erase(a.begin() + i);
                
                i = -1;
            }
        }
 
    }
    answer.push_back(lower);
    
 
    while (true)
    {
        
        if (n == m)
        {
            cout << n;
            answer.push_back(n);
            break;
        }
        else
        {
            if (n < m)
            {
                n += nn;
 
            }
            else
            {
                m += mm;
            }
        }
 
 
    }
 
cs

 

  • 시저 암호
  • darklight

    sublimevimemacs

    C++ 

문제 설명

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 AB는 1만큼 밀면 BC가 되고, 3만큼 밀면 DE가 됩니다. z는 1만큼 밀면 a가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한 조건

  • 공백은 아무리 밀어도 공백입니다.
  • s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
  • s의 길이는 8000이하입니다.
  • n은 1 이상, 25이하인 자연수입니다.

입출력 예

snresult

AB 1 BC
z 1 a
a B z 4 e F d

 

 

풀이)  아스키 코드를 보면 쉽게 알수있다  , 공백과 특수문자에 주의하면 쉬운문제

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    string s;
    int n = 25;
    s = "a B z";
    vector<int>ab;
    for (int i = 0; i < s.length(); i++)
    {
        if (s.at(i) != ' '//공백인가 아닌가 체크
        {
            if (s.at(i) >= 97// 소문자라면
            {
                if (s.at(i) + n <= 122)
                {
                    ab.push_back(s.at(i) + n);
 
                }
                else
                {
                    ab.push_back(s.at(i) + n - 26);
                }
            }
            else
            {
                if (s.at(i) + n <= 90)  //대문자라면
                {
                    ab.push_back(s.at(i) + n);
 
                }
                else
                {
                    ab.push_back(s.at(i) + n - 26);
                }
            }
        }
        else
        {
            ab.push_back(s.at(i));
        }
    }
    string answer;
 
    for (int i = 0; i < ab.size(); i++)
    {
        answer += char(ab.at(i));  //char형으로 바꾸어서 입력 아스키코드를
    }
    
    for (int i = 0; i < answer.length(); i++)
    {
        cout << answer.at(i);
    }
cs

 

 

 

  • 짝지어 제거하기
  • darklight

    sublimevimemacs

    C++ 

문제 설명

짝지어 제거하기는, 알파벳 소문자로 이루어진 문자열을 가지고 시작합니다. 먼저 문자열에서 같은 알파벳이 2개 붙어 있는 짝을 찾습니다. 그다음, 그 둘을 제거한 뒤, 앞뒤로 문자열을 이어 붙입니다. 이 과정을 반복해서 문자열을 모두 제거한다면 짝지어 제거하기가 종료됩니다. 문자열 S가 주어졌을 때, 짝지어 제거하기를 성공적으로 수행할 수 있는지 반환하는 함수를 완성해 주세요. 성공적으로 수행할 수 있으면 1을, 아닐 경우 0을 리턴해주면 됩니다.

예를 들어, 문자열 S = baabaa 라면

b aa baa → bb aa → aa 

의 순서로 문자열을 모두 제거할 수 있으므로 1을 반환합니다.

제한사항

  • 문자열의 길이 : 1,000,000이하의 자연수
  • 문자열은 모두 소문자로 이루어져 있습니다.

입출력 예

sresult

baabaa 1
cdcd 0

입출력 예 설명

입출력 예 #1
위의 예시와 같습니다.
입출력 예 #2
문자열이 남아있지만 짝지어 제거할 수 있는 문자열이 더 이상 존재하지 않기 때문에 0을 반환합니다.

 

 

 

풀이및 생각)

맨처음에는 정렬후 중복된건 삭제해줄려고햇는데 2번쨰 예시가 cdcd엿고 정렬시에는 제거할수있는 문자열이 되므로 안되고 

다음으로 생각한것은 string s에 erase를 사용하면 되지않나 싶었는데 

효율성에서 막히게 되었다.

그래서 어떤 컨테이너를 써야할거같은데 어떤것을 사용할까 싶었는데

vector 도 생각해보다 보니 또 삭제가 오래걸렷다는것을생각해보니 안되고

또다른 string에 해주는것도 효율성에서 통과하지않았고

list의 유니크 함수를 써볼려고햇는데

aa 라면 a가 남는데 a가 남는게 유니크를 써준 문자인지 확인하는것도 아니라는생각이들어서 

그다음으로 스택을 써보게 되었다.  

b    top b

b a     top a

b a  << a. push 전 체크를 할때 top 값이 a 이므로 중복체크가 되고 넘어가기에 빠른거같다. 

 

 

 

스택으로 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
string s = { "baabaa" };
int answer = 0;
 
stack<char> ss;
for (int i = 0; i < s.length(); i++)
{
    if (ss.empty() || ss.top() !=s[i])
    {
        ss.push(s.at(i));
    }
    else
    {
        cout << endl;
        cout << ss.top()<<" ";
        cout << s[i];
        ss.pop();
    }
}
 
if (ss.empty())
{
    answer = 0;
}
else
{
    answer = 1;
}
 
cout << answer;
 
 
cs

 

  • 구명보트
  • darklight

    sublimevimemacs

    C++ 

문제 설명

무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다.

예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없습니다.

구명보트를 최대한 적게 사용하여 모든 사람을 구출하려고 합니다.

사람들의 몸무게를 담은 배열 people과 구명보트의 무게 제한 limit가 매개변수로 주어질 때, 모든 사람을 구출하기 위해 필요한 구명보트 개수의 최솟값을 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 무인도에 갇힌 사람은 1명 이상 50,000명 이하입니다.
  • 각 사람의 몸무게는 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 항상 사람들의 몸무게 중 최댓값보다 크게 주어지므로 사람들을 구출할 수 없는 경우는 없습니다.

입출력 예

peoplelimitreturn

[70, 50, 80, 50] 100 3
[70, 80, 50] 100 3

 

 

풀이)

 

최대로 태울수 있는인원이 2명이다 

정렬을한뒤에 처음부터 태우면 되지않을까햇는데

테스트를 하다보니 젤큰숫자랑 젤작은숫자랑 태울수있으면 안되는 문제가 있어서 

그문제를 해결하기위해 정렬후 처음과 뒤부터 체크를 하면 되는것이었다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
    vector<int> people = { 40,50,50,60 ,40 ,60 };
    int limit = 100;
    int answer = 0;
 
    // 한 번에 최대 2명씩 밖에
 
 
    int weight = 0;
 
    sort(people.begin(), people.end());
    int start = 0;
    int end = people.size() - 1;
 
 
    while (true)
    {
 
        if (start != end)
        {
            if (weight == 0)
            {
                weight += people.at(start);
                start += 1;
 
            }
            else
            {
 
                if (weight + people.at(end) <= limit)
                {
                    end -= 1;
                    answer += 1;
                    weight = 0;
                }
                else
                {
                    end -= 1;
                    answer += 1;
 
                }
            }
        }
        else
        {
            if (weight + people.at(end) <= limit)
            {
                end -= 1;
                answer += 1;
                weight = 0;
            }
            else
            {
                answer += 2;
            }
            break;
        }
 
 
    }
 
cout << answer << endl;
cs

 

 

 

+ Recent posts