문제
출처 : https://www.acmicpc.net/problem/5875
5875번: 오타
올바른 괄호쌍을 좋아하는 키파는 최근에 노트북을 샀다. 그런데 키보드의 크기가 너무 작았기 때문에, 키파는 혹시 여는 괄호와 닫는 괄호를 서로 잘못 입력하지 않았는지 걱정되었다. 키
www.acmicpc.net
오타가 '최대 한번' 있는 괄호배열이 주어진다.
이 괄호배열의 괄호를 하나 조작하여 올바른 괄호 배열을 만드는 경우의 수 를 구하는 문제다.
풀이
어려웠던 문제다
누적합으로 풀었는데, 여는 괄호를 +1, 닫는괄호를 -1 이라고 하고 누적합 배열을 만들자.
예를들어, 괄호배열 ( ) 의 누적합배열은 {1, 0}, ( ( ) ) 의 누적합 배열은 {1, 2 ,1, 0}이 된다.
올바른 괄호배열이 여는괄호 '(' 가 있다면 이에 매칭되는 닫는괄호 ')'가 반드시 존재해야 한다는 것을 생각하면, 누적합 배열은 항상 0으로 끝나야하며, 어느 지점에서든지 음수가 나온다면, 여는괄호 보다 닫는괄호가 더 많은것을 의미하므로 누적합 배열에서 음수가 나오면 안된다는 것을 알 수 있다.
따라서, 이 문제는 다음과 같은 조건을 만족하는지 확인하며 O(N)만에 풀 수 있다.
1) 괄호배열의 어떤 지점을 수정했을때, 누적합 배열의 마지막이 0으로 끝나는가.
2) 괄호배열의 어떤 지점을 수정했을때, 누적합 배열에 음수가 존재하지 않는가.
1,2번을 만족한다면 수정된 괄호배열은 올바른 괄호배열이다.
위 과정을 괄호배열의 모든 지점마다 반복하면 된다.
이때, 1번 조건은 마지막지점에 +2 혹은 -2를 해가며 O(1)만에 구할 수 있지만 2번조건을 O(1)만에 구하는게 까다로웠다.
2번조건은 다시 두개의 조건으로 나뉜다.
1) 현재 수정하는 괄호가 닫는괄호 일때
-> 현재 수정하는 괄호가 닫는괄호라면, 누적합 배열의 이전 idx에서 음수가 있는지 확인한다. 음수가 존재한다면, 이 배열은 올바른 괄호배열이 될 수 없는데, 현재 위치의 닫는 괄호를 여는괄호로 수정하고 누적합 배열의 각 idx에 +2를 해줘도 이전 위치에는 영향을 미치지 않기 때문이다.
2) 현재 수정하는 괄호가 여는괄호 일때
-> 현재 위치의 여는괄호를 닫는괄호로 수정했을때, 누적합 배열의 이후 idx가 음수가 되는지 확인한다. 닫는괄호로 수정하면 누적합 배열의 각 idx에 -2를 해주므로, 누적합배열의 1과 0갯수를 누적합으로 만들어 체크해줌으로 O(1)에 구할 수 있다.
위 조건대로 코드를 만들면 답이 나온다.
(설명이 이해가 안되면 코드를 보도록 하자)
주요 소스코드
private int countBracketsFixablePointCount(String brackets){
int[] bracketSum = this.sumBrackets(brackets);
int leftMinusIdx = this.getLeftMinusIdx(bracketSum);
int[] leftPlusArray = this.getLeftPlusArray(bracketSum);
int fixablePoint = 0;
boolean fixed = false;
for(int i = 0; i < brackets.length(); i++){
fixed = false;
int lastPoint = bracketSum[bracketSum.length-1];
if(this.isCloseBracket(brackets.charAt(i)) && i < brackets.length()-1 && i <= leftMinusIdx) {
fixed = true;
lastPoint += 2;
}
else if(this.isOpenBracket(brackets.charAt(i)) && i > 0 && leftPlusArray[i] == 0){
fixed = true;
lastPoint -= 2;
}
if(lastPoint == 0 && fixed) fixablePoint++;
}
return fixablePoint;
}
전체소스코드
https://github.com/devxb/JJUNalgo/blob/master/5875%20%EC%98%A4%ED%83%80/Main.java
GitHub - devxb/JJUNalgo: 백준 알고리즘 소스코드🙃
백준 알고리즘 소스코드🙃. Contribute to devxb/JJUNalgo development by creating an account on GitHub.
github.com
'알고리즘 (2020 : 08 : 10 ~ ) > 구현, 시뮬' 카테고리의 다른 글
[백준 / BOJ] 17615 볼 모으기 (0) | 2023.01.03 |
---|---|
[백준 / BOJ] 16564 히오스 프로게이머 (누적합 풀이) (0) | 2022.06.04 |
[백준 / BOJ] 11509 풍선 맞추기 (0) | 2022.05.19 |
[백준 / BOJ] 22866 탑 보기 (0) | 2022.05.05 |
[programmers / kakao] 무지의 먹방 라이브 (Java) (0) | 2022.04.15 |