내가 생각했을때 문제에서 원하는부분
첫째 줄에 화학식이 주어진다.
화학식은 H, C, O, (, ), 2, 3, 4, 5, 6, 7, 8, 9만으로 이루어진 문자열이며, 그 길이는 100을 넘지 않는다.
첫째 줄에 화학식량을 출력한다.
분자량이 10,000이 넘는 고분자는 입력으로 주어지지 않는다.
내가 이 문제를 보고 생각해본 부분
초기 설정:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));: 콘솔로부터 입력을 효율적으로 읽어들이기 위해 BufferedReader를 사용한다.
String formula = br.readLine();: 사용자로부터 화학식 문자열을 입력받아 formula 변수에 저장한다.
Stack<Integer> stack = new Stack<>();: 정수형 값을 저장할 스택을 생성한다.
이 스택에는 각 원자의 질량, 괄호 그룹의 중간 합계 등이 저장된다.
int totalWeight = 0;: 최종적으로 계산된 화학식량을 저장할 변수이다.
화학식 문자열 순회:
for(char c : formula.toCharArray()): 입력받은 formula 문자열을 문자 배열로 변환하여 각 문자에 대해 반복문을 실행한다.
문자 종류별 처리 로직:
if(c == '(') (여는 괄호):
stack.push(0);: 여는 괄호를 만나면 스택에 0을 푸시한다.
이 0은 새로운 괄호 그룹의 시작을 알리는 일종의 표식이다.
이 0 위로 쌓이는 값들은 현재 괄호 안의 원자 또는 소그룹들의 질량이 된다.
else if (c == ')') (닫는 괄호):
int currentGroupWeight = 0;: 현재 괄호 그룹의 총 질량을 저장할 변수를 초기화한다.
while(!stack.isEmpty() && stack.peek() != 0) { currentGroupWeight += stack.pop(); }: 스택이 비어있지 않고, 맨 위의 값이 0이 아닐 때까지(즉, 현재 괄호 그룹 안의 모든 요소들을 만날 때까지) 스택에서 값을 하나씩 꺼내 currentGroupWeight에 더한다.
이 과정에서 H, C, O 원자의 질량이나, 중첩된 괄호 그룹의 계산 결과 등이 더해지게 된다.
stack.pop();: while 루프가 끝났다는 것은 0을 만났다는 뜻이므로, 그 0을 스택에서 제거한다. ((에 대한 표식을 제거하는 것이다.)
stack.push(currentGroupWeight);: 현재 괄호 그룹의 총 질량 (currentGroupWeight)을 다시 스택에 푸시한다.
이제 이 값은 하나의 원자 질량처럼 취급되어, 다음에 숫자가 오면 곱해질 수 있고, 더 큰 외부 괄호의 일부가 될 수도 있다.
else if (c >= '2' && c <= '9') (숫자):
int multiplier = c - '0';: 문자 c를 정수형 숫자(2~9)로 변환한다. (예: '2'는 2로, '9'는 9로)
int valueToMultiply = stack.pop();: 숫자는 항상 바로 앞에 오는 원자 또는 괄호 그룹의 개수를 의미한다.
따라서 스택의 가장 위에 있는 값(바로 앞에 처리된 원자 질량 또는 괄호 그룹의 합)을 꺼낸다.
stack.push(valueToMultiply * multiplier);: 꺼낸 값에 multiplier를 곱한 후 다시 스택에 푸시한다.
else(원자: 'H', 'C', 'O'):
if(c == 'H') { stack.push(1); }: 수소 원자를 만나면 질량 1을 스택에 푸시한다.
else if (c == 'C') { stack.push(12); }: 탄소 원자를 만나면 질량 12를 스택에 푸시한다.
else if (c == 'O') { stack.push(16); }: 산소 원자를 만나면 질량 16을 스택에 푸시한다.
이 값들은 바로 뒤에 숫자가 오면 곱해지고, 괄호 그룹 내에서는 다른 값들과 합쳐지게 된다.
최종 화학식량 계산:
while(!stack.isEmpty()) { totalWeight += stack.pop(); }: 화학식 문자열의 모든 문자를 처리한 후, 스택에는 남아있는 모든 원자 질량이나 그룹 질량들이 존재한다.
이들을 모두 꺼내 totalWeight에 합산하면 최종 화학식량이 된다. (예: H2O의 경우, H2의 2와 O의 16이 각각 스택에 남아있을 수 있다. 이것들을 더하면 18이 된다.)
System.out.println(totalWeight);: 최종 계산된 화학식량(totalWeight)을 출력한다.
br.close();: BufferedReader를 닫아 자원을 해제한다.
코드로 구현
package baekjoon.baekjoon_30;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
// 백준 2257번 문제
public class Main1149 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String formula = br.readLine(); // 화학식 입력 받기
Stack<Integer> stack = new Stack<>();
int totalWeight = 0; // 최종 화학식량을 저장할 변수
for(char c : formula.toCharArray()) { // 화학식의 각 문자를 순회
if(c == '(') {
// 여는 괄호를 만나면 현재까지 계산된 부분합을 0으로 초기화하고 스택에 0을 푸시합니다.
// 이 0은 해당 괄호 안의 원자들의 무게 합을 위한 기준점 역할을 합니다.
stack.push(0);
} else if(c == ')') {
int currentGroupWeight = 0;
// 닫는 괄호를 만나면 스택에서 여는 괄호 '('에 해당하는 0이 나올 때까지 pop하여 합산합니다.
while(!stack.isEmpty() && stack.peek() != 0) {
currentGroupWeight += stack.pop();
}
stack.pop(); // 괄호 시작을 나타내는 0을 제거합니다.
stack.push(currentGroupWeight); // 괄호 안의 전체 합을 다시 스택에 푸시합니다.
} else if(c >= '2' && c <= '9') {
// 숫자를 만나면 스택의 가장 위에 있는 값(원자 또는 괄호 그룹의 합)을 숫자만큼 곱합니다.
int multiplier = c - '0'; // 문자를 정수형 숫자로 변환
int valueToMultiply = stack.pop();
stack.push(valueToMultiply * multiplier);
} else { // 'H', 'C', 'O' 원자인 경우
// 각 원자의 질량을 스택에 푸시합니다.
if(c == 'H') {
stack.push(1);
} else if(c == 'C') {
stack.push(12);
} else if(c == 'O') {
stack.push(16);
}
}
}
// 모든 문자를 처리한 후, 스택에 남아있는 모든 값들을 합산하여 최종 화학식량을 계산합니다.
while(!stack.isEmpty()) {
totalWeight += stack.pop();
}
System.out.println(totalWeight); // 최종 화학식량 출력
br.close();
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.