Algorithm

[프로그래머스] 수식 최대화(2020 카카오 인턴십)

HONGNEW 2021. 1. 8. 22:12

 

프로그래머스에서 2020 카카오 인턴십 코테 출제 문제였던 수식 최대화 문제를 풀어보았습니다.

 

+, -, * 3가지의 연산자만을 포함하는 수식이 주어졌을 때, 연산자의 우선순위를 재정의하여 산출할 수 있는 가장 큰 수를 구하는 문제입니다.

이 문제를 풀기 위해서 고려해야 하는 사항은 다음과 같습니다.

 

1. 우선순위 조합 만들기

2. 순서에 따라 수식 계산하기

 

1. 우선순위 조합 만들기

우선순위의 조합은 순서가 있는 조합이므로 순열을 이용합니다.

n개 중 r개를 골라 순서가 있는 조합을 만드는 경우에는 아래 코드의 for 문을 n번, if 문에서의 depth조건을 r로 설정하면 됩니다.

이 문제의 경우에는 3개의 연산자 중 3개를 모두 사용해서 순서를 뽑으므로 3을 하드 코딩했습니다.

 

재귀 함수를 통해 모든 경우의 수를 찾아줍니다.

 

 public void priorityPerm(char[] prioritys, boolean[] visited, int depth){
        char[] operations = {'*','+','-'};
        if(depth==3) {
            for(int a=0; a<3; a++)
            opPriority[cnt][a] = prioritys[a];
            cnt++;
        };
        for(int i = 0; i<3; i++){
            if(!visited[i]){
                visited[i] = true;
                prioritys[depth] = operations[i];
                priorityPerm(prioritys, visited, depth+1);
                visited[i] = false;
            }
        }
    }

 

2. 순서에 따라 수식 계산하기

문제를 풀면서 가장 애먹었던 부분이 바로 이 부분이었습니다.

수식을 계산하는 부분을 어떻게 구현할까 한참을 고민하다가 후위 계산식으로 변환하여 처리했습니다.

주어진 수식을 연산자 우선순위를 반영하여 후위 계산식으로 변환하고, Stack을 이용해 수식을 계산해줍니다.

public long calOperation(String[] operations,char[] type){
        Stack <String> priority = new <String> Stack();
        Stack <Long> cal = new <Long> Stack();
        HashMap <Character, Integer> hm = new <Character, Integer> HashMap();
        ArrayList <String> list = new ArrayList<String>();
        for(int a=0; a<type.length; a++){
            System.out.println(type[a]);
            hm.put(type[a], a+1);
        }
        for(int i=0; i<operations.length; i++){
            if(operations[i].equals("*")||operations[i].equals("+")||operations[i].equals("-")){
                while(!priority.isEmpty()&&hm.get(operations[i].charAt(0))>=hm.get(priority.peek().charAt(0))){
                    list.add(priority.pop());
                }
                priority.push(operations[i]);
            }else{
                list.add(operations[i]);
            }
        }
        while(!priority.isEmpty()){
            list.add(priority.pop());
        }
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i));
            if(list.get(i).equals("*")){
                long a = cal.pop();
                long b = cal.pop();
                cal.push(a*b);
            }else if(list.get(i).equals("+")){
                long a = cal.pop();
                long b = cal.pop();
                cal.push(a+b);
            }else if(list.get(i).equals("-")){
                long a = cal.pop();
                long b = cal.pop();
                cal.push(b-a);
            }else {
                cal.push(Long.parseLong(list.get(i)));
            }
        }
        return cal.pop();
    }

 

전체 코드

주어진 수식을 숫자와 연산자로 분리하는 부분이 깔끔하지 못해서 아쉽고, 수식에 포함되지 않는 연산자를 제외하는 등의 처리를 더 해주면 좋을 것 같습니다.

import java.util.*;
class Solution {
    static char[][] opPriority = new char[6][3];
    static int cnt;
    public long solution(String expression) {
    long answer = 0;
    long maxResult = 0;
    char[] prioritys = new char[3];
    boolean[] visited = new boolean[3];
    String temp = expression.replaceAll("\\+", "&+&");
           temp = temp.replaceAll("\\-", "&-&");
           temp = temp.replaceAll("\\*", "&*&");
    String[] array = temp.split("&");

    priorityPerm(prioritys, visited, 0);
        for(int i=0; i<6;i++) {
            maxResult = calOperation(array, opPriority[i]);
            if(maxResult<0) maxResult *= -1;
            answer = maxResult > answer ? maxResult : answer;
        }
        return answer;
    }
    public void priorityPerm(char[] prioritys, boolean[] visited, int depth){
        char[] operations = {'*','+','-'};
        if(depth==3) {
            for(int a=0; a<3; a++)
            opPriority[cnt][a] = prioritys[a];
            cnt++;
        };
        for(int i = 0; i<3; i++){
            if(!visited[i]){
                visited[i] = true;
                prioritys[depth] = operations[i];
                priorityPerm(prioritys, visited, depth+1);
                visited[i] = false;
            }
        }
    }
    public long calOperation(String[] operations,char[] type){
        Stack <String> priority = new <String> Stack();
        Stack <Long> cal = new <Long> Stack();
        HashMap <Character, Integer> hm = new <Character, Integer> HashMap();
        ArrayList <String> list = new ArrayList<String>();
        for(int a=0; a<type.length; a++){
            System.out.println(type[a]);
            hm.put(type[a], a+1);
        }
        for(int i=0; i<operations.length; i++){
            if(operations[i].equals("*")||operations[i].equals("+")||operations[i].equals("-")){
                while(!priority.isEmpty()&&hm.get(operations[i].charAt(0))>=hm.get(priority.peek().charAt(0))){
                    list.add(priority.pop());
                }
                priority.push(operations[i]);
            }else{
                list.add(operations[i]);
            }
        }
        while(!priority.isEmpty()){
            list.add(priority.pop());
        }
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i));
            if(list.get(i).equals("*")){
                long a = cal.pop();
                long b = cal.pop();
                cal.push(a*b);
            }else if(list.get(i).equals("+")){
                long a = cal.pop();
                long b = cal.pop();
                cal.push(a+b);
            }else if(list.get(i).equals("-")){
                long a = cal.pop();
                long b = cal.pop();
                cal.push(b-a);
            }else {
                cal.push(Long.parseLong(list.get(i)));
            }
        }
        return cal.pop();
    }
}