5줄의 문자들을 입력받아야하는데 이때 한줄에 문자는 15개가 최대로 올 수 있다. 빈칸없이 연속으로 주어져서 어떻게 풀어야할지 고민을 했는데 생각해보면 문자열로 배열처럼 접근할 수 있기 때문에 한줄씩 받은 다음 접근을 세로로 하면 된다.

 

정답코드

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    vector<string> v(5, ""); // 5줄의 문자열 벡터 생성

    // 입력 받기
    for (int i = 0; i < 5; i++)
    {
        getline(cin, v[i]); // 한 줄씩 입력받아 벡터에 저장
    }

    // 세로로 읽어서 출력
    for (int i = 0; i < 15; i++) // 최대 15개의 열
    {
        for (int j = 0; j < 5; j++) // 5개의 행
        {
            if (i < v[j].size()) // 현재 행의 i번째 문자가 존재하면 출력
            {
                cout << v[j][i];
            }
        }
    }

    return 0;
}

단어를 입력으로 받았을 때, 몇개의 단어가 그룹단어인지 개수를 출력해주면 된다.

이때 그룹단어는 같은 단어가 연속해서 나타나는 경우를 의미한다.

소문자의 개수만큼 bool vector를 선언하고 단어의 알파벳을 하나씩 순회하는데 이전에 나온 알파벳과 비교하여 다를 

경우 방문했는지 체크하고 방문했다면 false를 반환해주고 다 체크했을 때 이상이 없으면 true를 반환해주는 함수를 통해 그룹함수인지를 체크하자.

 

정답코드

#include <iostream>
#include <vector>

using namespace std;

bool isGroup(string s);

int main()
{
	int n;
	cin >> n;

	int count = 0;

	for (int i = 0;i < n;i++)
	{
		string s;
		cin >> s;
		if (isGroup(s))
		{
			count++;
		}
	}

	cout << count;
}

bool isGroup(string s)
{
	vector<bool> visited(26, false);

	char pre_c = ' ';

	for (char c : s)
	{
		//만약 전에 나왔던 알파벳과 다르다면
		if (c != pre_c)
		{
			//방문하지 않았던 거라면
			if (!visited[c - 'a'])
			{
				visited[c - 'a'] = true;
				pre_c = c;
				continue;
			}
			else  //방문했었던거라면 그룹단어가 아님
			{
				return false;
			}
		}
	}

	return true;
}

 

문자를 입력받고 가장 많이 사용된 알파벳을 출력해주는데 만약 가장 많이 사용된 알파벳이 여러개 있다면 ?를 출력해주면 된다.

 

처음에 map을 사용하여 풀어서 정답이었지만 다음과 같은 문제점이 있어서 코드를 수정해보았다.

 

  • map<char, int> 대신 array 사용
    • map은 내부적으로 Red-Black Tree 구조를 사용하여 삽입과 조회가 O(log N) 소요됨.
    • 하지만 알파벳 개수는 26개로 고정되어 있으므로, 배열(array<int, 26>)을 사용하면 O(1)으로 빠르게 접근 가능.
  • tolower() 변환 시 불필요한 중복 연산 제거
    • 현재 tolower()를 여러 번 호출하고 있지만, 한 번 변환한 후 바로 인덱스로 사용하면 중복 연산 감소.
  • 최댓값 찾기 및 중복 체크를 하나의 반복문으로 수행
    • 현재는 두 개의 반복문을 사용하여 최댓값과 중복 여부를 검사 (O(N) + O(26))
    • 한 번의 반복문(O(26))으로 최댓값과 중복 여부를 처리하여 최적화 가능

 

 

정답코드(map사용)

#include <iostream>
#include <cctype>
#include <map>

using namespace std;

map<char, int> m;
int main()
{
	string s;
	cin >> s;
	
	for (int i = 0;i < s.length();i++)
	{
		m[tolower(s[i])]++;
	}
	
	int max_value = m[s[0]];
	char max_char = s[0];
	int cnt = 0;

	for (const auto& pair : m) {
		if (max_value < pair.second)
		{
			max_value = pair.second;
			max_char = pair.first;
		}
	}

	for (const auto& pair : m) {
		if (max_value == pair.second)
		{
			cnt++;
		}
	}

	if (cnt > 1)
	{
		cout << "?";
	}
	else
	{
		cout << char(toupper(max_char));
	}
}

 

정답코드(효율적, Array사용)

#include <iostream>
#include <array>

using namespace std;

int main()
{
    string s;
    cin >> s;

    array<int, 26> freq = { 0 }; // 알파벳 개수(26) 만큼 배열 생성 및 초기화

    // 문자 개수 세기
    for (char c : s)
    {
        freq[tolower(c) - 'a']++;
    }

    // 최댓값 찾기 & 중복 체크
    int max_value = 0, max_index = -1;
    bool is_duplicate = false;

    for (int i = 0; i < 26; i++)
    {
        if (freq[i] > max_value)
        {
            max_value = freq[i];
            max_index = i;
            is_duplicate = false; // 새로운 최댓값이 나오면 중복 여부 초기화
        }
        else if (freq[i] == max_value)
        {
            is_duplicate = true;
        }
    }

    // 출력
    if (is_duplicate)
        cout << "?";
    else
        cout << char(max_index + 'A'); // 대문자로 변환

    return 0;
}

 

100줄을 입력받아서 그대로 출력해줘야하기 때문에 ostringstream을 사용해보았다. getline을 통해 한줄씩 ostringstream에 추가하고 공백을 입력받으면 마지막에 한번에 출력해주는 방식을 사용하였다.

 

정답코드

#include <iostream>
#include <sstream>


using namespace std;


int main()
{
	ostringstream output;

	while (1)
	{
		string s;
		getline(cin, s);
		if (s.empty()) break;

		output << s << "\n";
	}

	cout << output.str();

	return 0;
}

 

문제의 규칙성을 찾아야한다. 일단 알파벳이 아닌 1까지 가는 시간이 2초가 걸리기 때문에 A부터 C까지는 3초가 걸리고 D~F까지는 4초가 걸린다. 이때 4개의 알파벳이 있는 수도 있기 때문에 예외처리를 해주어야 한다. 

 

 

정답코드

#include <iostream>

using namespace std;


int main()
{
	int sum = 0;
	string s;
	cin >> s;

	for (char c : s)
	{
		//기본이 2초 알파벳 3개가 지날 때마다 1초씩 증가
		sum += ((int)c-65) / 3 + 3;

		if (c == 'S' || c == 'V' || c == 'Y' || c == 'Z') sum--;
	}
	
	cout << sum;

	return 0;
}

 

테스트 케이스 마다 각 문자를 R번 반복한다. 이때 outputstream을 사용하여 문자열 연결 성능 최적화하고 string 함수를 통해 해당 문자를 반복해서 들어가도록 해주자.

 

정답코드

#include <iostream>
#include <string>
#include <sstream>  

using namespace std;

int main()
{
    int t;
    cin >> t;

    

    while (t--)
    {
        ostringstream output; // 전체 출력을 저장할 스트림
        int r;
        string s;
        cin >> r >> s;

        for (char c : s)  // `s[j]` 대신 range-based for loop 사용
        {
            output << string(r, c);  // 문자를 r번 반복하여 추가
        }
        cout << output.str()<<"\n";  // 최종 출력
       
    }

    

    return 0;
}

'코딩테스트 > 백준' 카테고리의 다른 글

[백준][C++]11718번. 그대로 출력  (0) 2025.03.06
[백준][C++]5622번. 다이얼  (0) 2025.03.06
[백준][C++]1546번. 평균  (0) 2025.03.06
[백준][C++]10811번. 바구니 뒤집기  (0) 2025.03.06
[백준][C++]2562번. 최댓값  (0) 2025.03.06

 

주어진 점수를 배열에 입력받고 최대값을 max_element를 통해 구하고 이를 통해 새로운 점수의 합을 계산

평균을 구해주면 된다.

이때 나눗셈을 할때 static_cast를 통해 double로 캐스팅을 해주어야 값의 손실이 없다. 그리고 소숫점 6자리까지 출력하게 해주는 코드는 다음과 같다.

  cout << fixed;
  cout.precision(6); // 소수점 6자리까지 출력

 

 

정답코드

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

using namespace std;


int main()
{
    int n;
    cin >> n;
    vector<int> v(n);
    for (int i = 0;i<n;i++)
    {
        cin >> v[i];
    }

    int m = *max_element(v.begin(), v.end());
    double sum = 0.0;
    for (int i:v)
    {
        sum += (static_cast<double>(i) / m * 100);
    }

    cout << fixed;
    cout.precision(6); // 소수점 6자리까지 출력
    cout << sum / n << "\n"; // 평균 출력

    return 0;
}

 

n 길이의 배열을 각 인덱스로 초기화한 다음 m번동안 i번째부터~j번째까지를 뒤집어주면 된다.

이때 reverse 함수를 활용하여 풀 수 있다.

 

reverse함수는 시작과 끝을 정해주면 그 구간을 뒤집어 준다.

 

정답코드

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

using namespace std;


int main()
{
    int n, m;
    cin >> n >> m;
    
    vector<int> v(n);

    for (int i = 0;i < n;i++)
    {
        v[i] = i + 1;
    }

    for (int x = 0;x < m;x++)
    {
        int i, j;
        cin >> i >> j;
        reverse(v.begin() + i - 1, v.begin() + j);
    }
    
    for (int it : v)
    {
        cout << it << " ";
    }

    return 0;
}

 

배열을 입력받고 최댓값과 그 값이 몇 번째 수인지 출력하면 된다.

max_element함수를 통해 최댓값을 출력해주고

이 함수에서 v.begin()을 빼주는 것으로 index도 알아내자. 이때 index로 나오기 때문에 +1을 해주어야한다.

 

이렇게 되는 이유는

vector는 일련의 반복자로 구성되어 있으므로 최대값을 가리키는 반복자를 맨 처음을 가리키는 v.begin()만큼 빼준다면 인덱스 값을 구할 수 있다.

 

정답코드

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

using namespace std;

int main()
{
    vector<int> v(9);
    for (int i = 0;i < 9;i++)
    {
        cin >> v[i];
    }

    cout << *max_element(v.begin(), v.end()) <<"\n" << max_element(v.begin(), v.end()) - v.begin() + 1;

    return 0;
}

https://www.acmicpc.net/problem/10818

 

수의 배열을 입력받고 최솟값과 최댓값을 출력해주면 되는 문제이다. 처음에 정렬한 다음 처음과 끝 값을 출력하려고 했는데 정렬이 nlogn의 시간이 걸리고 min max element를 출력해주는 함수는 n의 시간이 걸리기 때문에 더 효율적이라고 한다.

 

하지만 limits 라이브러리를 활용하여 배열을 사용하지 않고도 이 문제를 해결할 수도 있다. 이때 limits함수의 max min을 저장해두고 만약 더 큰값이나 더 작은 값이 있다면 이 값으로 변경해주면 된다.

 

정답코드(배열 사용)

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

using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<int> v(n);
    for (int i = 0;i < n;i++)
    {
        cin >> v[i];
    }

    cout << *min_element(v.begin(),v.end()) << " " << *max_element(v.begin(),v.end());

    return 0;
}

 

정답코드(limits 라이브러리 사용)

#include <iostream>
#include <limits>

using namespace std;

int main() {
    int n, num;
    cin >> n;

    int minVal = numeric_limits<int>::max();
    int maxVal = numeric_limits<int>::min();

    for (int i = 0; i < n; i++) {
        cin >> num;
        if (num < minVal) minVal = num;
        if (num > maxVal) maxVal = num;
    }

    cout << minVal << " " << maxVal << "\n";
    return 0;
}

+ Recent posts