PS/BaekJoon

[5430] AC - 구현/문자열/덱 ★★☆☆ / 복습 ○

JIK_ 2021. 11. 26. 08:25

[ 문제 ] : https://www.acmicpc.net/problem/5430

 

5430번: AC

각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 만약, 에러가 발생한 경우에는 error를 출력한다.

www.acmicpc.net


[ 문제 접근 ]

 

문제 이름 답게 풀다 보면 에이씨.. 가 절로 나오는 그런 문제다.

 

 처음 문제를 읽고

 

① 입력으로 주어진 [1,2,3,4] 을 1 2 3 4 로 split 하는 부분.

② reverse 하는 부분.

 

이 관건이겠구나.  싶었다.

 

아래는 내 긴 여정이 담긴 최종 코드다. 

어디서 해맸는지 자세하게 기록해보자.

 

그래도 이 문제 풀고 얻어 간게 몇 가지 있었다 ;)


[ 최종 코드 ]

 

#include<iostream>
#include<algorithm>
#include<deque>
#include<string>
#include<sstream>

using std::cout; using std::cin;
using std::deque; using std::string;

int n, t;
string p;
string s_arr;

deque<int> split(string input, char delimeter) {
	deque<int> answer;
	
	input.erase(input.begin()); //input.erase(0)      '['  지움
	input.erase(input.end() - 1);             //      ']'  지움


	std::stringstream ss(input);
	string num = "";
	while (getline(ss, num, delimeter)) {
		answer.push_back(std::stoi(num));
	}
	return answer;
}


int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	cin >> t;
	while (t--) {
		cin >> p;
		cin >> n;
	
		cin.ignore(10, '\n');
		getline(cin, s_arr);

		s_arr.erase(s_arr.begin()); //input.erase(0)  '['  지움
		s_arr.erase(s_arr.end()-1);                  // ']'  지움

		deque<int> arr = split(s_arr,',');

		bool is_error = false;
		bool reverse = false;

		for (size_t i = 0; i < p.length(); i++) {
			if (p[i] =='R') {
				//std::reverse(arr.begin(), arr.end());
				reverse = !reverse;
			}
			else {
				if (arr.empty()) { 
					cout << "error\n";
					is_error = true;
					break;
				}
				if (reverse) {
					arr.pop_back();
				}
				else {
					arr.pop_front();
				}
			}
		}
		// 출력
		if (!is_error) {
			if (arr.empty()) {
				cout << "[]\n";
			}
			else {
				cout << "[";
				if (reverse) {
					for (auto ritr = arr.rbegin(); ritr != arr.rend(); ritr++) {
						if (ritr == arr.rend()-1) {
							cout << *ritr;
							break;
						}
						cout << *ritr << ",";
					}
				}
				else {
					for (int i = 0; i < arr.size(); i++) {
						if (i == arr.size() - 1) {
							cout << arr[i];
							break;
						}
						cout << arr[i] << ",";
					}
				}
				cout << "]\n";
			}
		}
		s_arr.clear();
	}

	return 0;

}

 

 

 

자기전에 한 문제만 풀고 자려다가 피 봤다..

차라리 저 틀렸습니다 가 더 좋더라 요샌.. 

 

 


[ Key Point ]

 

👉 우선 14 ~ 27  split 함수 부터 보자.   

deque<int> split(string input, char delimeter) {
	deque<int> answer;
	
        input.erase(input.begin()); //input.erase(0)      '['  지움
	input.erase(input.end() - 1);                  // ']'  지움
    
	std::stringstream ss(input);
	string num = "";
	while (getline(ss, num, delimeter)) {
		answer.push_back(std::stoi(num));
	}
	return answer;
}
input.erase(input.end() - 1); // ']' 지움

' ] ' 지우려고 처음에는 input.erase(input.end()); 이렇게 썼는데 ] 가 지워지지 않았다.

 

그래서 erase 함수를 급하게 찾아보니 

1. iterator erase (const_iterator position);
2. iterator erase (const_iterator first, const_iterator last);

1 번은 pos 의 값 지우는거고,   2번은 first 부터 last 전까지 지우는거다. 

나는 1번을 사용해야하니 end() 가 아닌 end()-1을 해야 마지막 원소를 지울 수 있다.

 

나머지는 평범한 stringstream을 이용한 평범한 split 함수.

 


 

👉 원래는 deque 이 아니라 vector를 이용해서 풀었었다. 그러다가 자꾸 오류 나니깐 괜히 벡터 때문인가 싶어서 벡터를 덱으로 바꾼거다.

( 풀고 보니 벡터를 사용하면 시간 초과가 나온다는 글 들을 여럿 봤다.

벡터 원소 삭제시 한 칸씩 땡겨지는데 이 과정이 reverse 와 마찬가지로 O(N) 의 시간복잡도를 가지기 때문. )

 

 

<algorithm> 에 있는 reverse 함수를 사용했는데 이러면 시간초과 가 뜬다.

//std::reverse(arr.begin(), arr.end());
reverse = !reverse;

그래서 bool 타입 reverse flag 하나 만들어서 reverse가 true 면 원소를 뒤에서 pop 하고 false면 앞에서 pop 하게끔 구현했다.

if (reverse) {
	arr.pop_back();
}
else {
	arr.pop_front();
}

 

👉 계속 오류가 나서 다른 사람 블로그를 보다가 이 부분을 보고 풀 수 있었다.

 


👉 계속 하는 실수인데 test case 가 여러개 주어질때는 항상 전역변수 초기화하는거 잊지 말자!! 

이것 때문에도 몇번 틀렸다.

 

s_arr.clear();


[ 다른 사람 풀이 ]

 

ref :: https://koolreview.tistory.com/65

ref ::