BaekJoon : 1541번(잃어버린 괄호)

Java : BaekJoon Greedy

BaekJoon Greedy 저의 문제풀이 입니다.

혹시 더 좋은 방법 알려주신다면 정말 감사하겠습니다!

1541

세준이는 양수와 +, -, 그리고 괄호를 가지고 식을 만들었다. 그리고 나서 세준이는 괄호를 모두 지웠다.

그리고 나서 세준이는 괄호를 적절히 쳐서 이 식의 값을 최소로 만들려고 한다.

괄호를 적절히 쳐서 이 식의 값을 최소로 만드는 프로그램을 작성하시오.

첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 많이 연속되는 숫자는 없다. 수는 0으로 시작할 수 있다. 입력으로 주어지는 식의 길이는 50보다 작거나 같다.

첫째 줄에 정답을 출력한다.

55-50+40	// 수식을 입력하면
-35		// 괄호를 이용해 만들 수 있는 최소값이 나옵니다.

방법1

최소 값을 구하기 위해 처음 -를 만나는 이후의 값을 전부 더해서 -연산을 해주었습니다.

예를 들어 55-50+40+30+10-35 가 있다고 했을 때, 55는 첫번 째 값이니 그냥 더해주고 처음 만나는 --50 이후의 값들을 전부 더합니다 50+40+30+10+35=165 이 값을 55에서 빼주면 -110으로 최소값이 나오게 됩니다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		
		OutputStreamWriter osw = new OutputStreamWriter(System.out);
		BufferedWriter bw = new BufferedWriter(osw);
		
		try {
			String equation = br.readLine().trim();
			StringTokenizer stk = new StringTokenizer(equation,"+-",true);
			
			List<Integer> nums = new ArrayList<>();
			List<Character> signs = new ArrayList<>();
			
			// '+'와 '-'로 나눈 토큰을 순회하여 토큰을 Object객체로 받고
			// try catch를 이용해 int형으로 형변환이 가능하면 int로 바꾸고 아니면 char형으로 바꿉니다. 
			while(stk.hasMoreElements()) {
				Object numOrSign = stk.nextElement();
				try {
					int num = Integer.parseInt((String)numOrSign);
					nums.add(num);
				} catch (NumberFormatException e) {
					char sign = numOrSign.toString().charAt(0);
					signs.add(sign);
				}
			}
			
			int tempsum = 0;
			int sum = nums.get(0);
			boolean meetMinus = false;
			
			// 첫번째 인덱스는 무조건 양수이므로, 숫자리스트의 1부터 순회하며 '-'를 만나기 전까지의 값은 총 합계에 더해주고
			// -를 만난뒤의 값은 임시합계에 다 더해준다음 "총합계 - 임시합계"를 합니다.
			for (int i = 1; i < nums.size(); i++) {
				if(signs.get(i-1) == '-')
					meetMinus = true;
				
				if(meetMinus)
					tempsum += nums.get(i);
				else 
					sum += nums.get(i);
			}
			sum -= tempsum;
			
			bw.write(Integer.toString(sum));
			bw.flush();
			bw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

방법2

먼저 식을 -를 기준으로 토큰으로 나눕니다. 그럼 +연산인 토큰들만 남는데, 이 토큰들을 +를 기준으로 나눈 후, 전부 더해서 총 합계에서 빼줍니다(이 때, 첫번 째 토큰은 무조건 양수이므로 주의해야합니다.)

예를 들어 55-50+40+30+10-35 에서 -기준으로 나누면 55, 50+40+30+10, 35 가 되는데, 이 나누어진 토큰들을 더해주고(55, 130, 35) 첫 번째 토큰을 제외한 나머지 토큰들을 빼줍니다.(55-130-35 = 110)

package Greedy;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class g1541_2 {
	public static void main(String[] args) {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		
		OutputStreamWriter osw = new OutputStreamWriter(System.out);
		BufferedWriter bw = new BufferedWriter(osw);
		
		try {
			String equation = br.readLine().trim();
			StringTokenizer minusStk = new StringTokenizer(equation,"-");
			
			int sum = 0;
			boolean firstToken = true;
			
			// '-'를 기준으로 나눈 토큰을 순회면서 나눈 토큰을 '+' 로 또 나누고 '+'로 나눈 토큰들을 임시합계에 더해줍니다.
			// '-'로 나누었을 때, 첫번 째 토큰이면 "총 합계 += 임시합계", 다른 토큰이면 "총 합계 -= 임시합계". 즉, "첫 번째 토큰 - 나머지 토큰"이 됩니다.
			while(minusStk.hasMoreTokens()) {
				int tempsum = 0;
				StringTokenizer plusStk1 = new StringTokenizer(minusStk.nextToken(),"+");
				
				while(plusStk1.hasMoreTokens()) {
					int num = Integer.parseInt(plusStk1.nextToken());
					
					tempsum += num;
				}
				
				if(firstToken) {
					sum += tempsum;
					firstToken = false;
				}
				else
					sum -= tempsum;
			}
			
			bw.write(Integer.toString(sum));
			bw.flush();
			bw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

참고 : https://st-lab.tistory.com/148


해당 코드들은 저의 GitHub에서 확인할 수 있습니다.

댓글남기기