출처 : https://www.acmicpc.net/problem/10799
여러 개의 쇠막대기를 레이저로 절단하려고 한다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자른다. 쇠막대기와 레이저의 배치는 다음 조건을 만족한다.
쇠막대기는 자신보다 긴 쇠막대기 위에만 놓일 수 있다. - 쇠막대기를 다른 쇠막대기 위에 놓는 경우 완전히 포함되도록 놓되, 끝점은 겹치지 않도록 놓는다.
이러한 레이저와 쇠막대기의 배치는 다음과 같이 괄호를 이용하여 왼쪽부터 순서대로 표현할 수 있다.
레이저는 여는 괄호와 닫는 괄호의 인접한 쌍 ‘( ) ’ 으로 표현된다. 또한, 모든 ‘( ) ’는 반드시 레이저를 표현한다.
쇠막대기의 왼쪽 끝은 여는 괄호 ‘ ( ’ 로, 오른쪽 끝은 닫힌 괄호 ‘) ’ 로 표현된다.
위 예의 괄호 표현은 그림 위에 주어져 있다.(그림은 위 링크 참고)
쇠막대기는 레이저에 의해 몇 개의 조각으로 잘려지는데, 위 예에서 가장 위에 있는 두 개의 쇠막대기는 각각 3개와 2개의 조각으로 잘려지고, 이와 같은 방식으로 주어진 쇠막대기들은 총 17개의 조각으로 잘려진다.
쇠막대기와 레이저의 배치를 나타내는 괄호 표현이 주어졌을 때, 잘려진 쇠막대기 조각의 총 개수를 구하는 프로그램을 작성하시오
먼저, barCount를 측정할 변수를 하나 선언한다.
그리고 다음의 규칙을 따른다.
1. ( 가 나오면 무조건 barCount를 +1 시킨다.
2. ) 가 나오면 다음의 조건을 따른다.
왜 이렇게 풀까? 먼저 이런 문제는, 이미 결과를 보고 쇠막대기를 자르려고 하면 머리가 아프다. 그러기 때문에, 앞에서부터 차근차근 반복문이 돌 때마다 상태가 어떻게 변하는지 관찰하는게 중요하다고 생각한다.
문제의 예시를 보자.
이 그림을 보면, 레이저가 생길 때, barCount 만큼 잘린 쇠막대기들이 생성됨을 볼 수 있다. 너무 당연한 사실이다.
따라서, 위 조건에 따라, 레이저면 barCount를 1 감소 시키고 barCount 개수를 answer에 더해주어야 한다.( 1을 감소 시켜주는 이유는 레이져를 표현하기 때문)
두 번째 예시를 보자.
이미 이전 괄호가 닫힌 괄호인데 또 닫힌 괄호가 오면 이는 쇠막대기의 종료를 말한다. 그러면 쇠막대기는 무조건 잘려서 나온다. 생각해보면, 1개 이상의 쇠막대기를 표현하기 위해서는 반드시 안에 레이저가 존재한다. 따라서, 잘려나온 쇠막대기 하나가 생성되므로 answer에 +1을 해주고, 쇠막대기 하나가 다 잘렸으므로 barCount 를 1 감소 시켜준다.
간단하다. 입력 로직은 생략하겠다.
prev는 이전의 괄호의 상태를 저장하는 변수이다.
function solve() {
let barCount = 0;
let answer = 0;
let prev = '';
for(let c of input){
if( c == '('){
barCount++;
prev = '(';
}
else if(c == ')'){
if(prev == '('){
barCount -= 1;
answer += barCount;
}
else if(prev == ')'){
answer += 1
barCount--;
}
prev = ')';
}
}
console.log(answer);
}
시간복잡도는 문자열의 길이가 N이라면, O(N). N이 최대 10만이므로 손쉽게 처리 가능하다.
처음에는 이상하게 생각해서 시간이 오래걸렸다.
밑에 힌트를 보지말자!! 괜히 생각하는 길을 막는 것 같다.
나름 성장한 거 같은 느낌^_^