코테/프로그래머스

[프로그래머스] 튜플 - java

tony1724 2025. 5. 10. 14:02

문제 설명 :

https://school.programmers.co.kr/learn/courses/30/lessons/64065

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

 

문제 요약 :

  1. 특정 튜플을 표현하는 집합이 담긴 문자열 s가 주어진다.
  2. s가 표현하는 튜플을 배열에 담아 반환

 

문제 풀이 시간 : 40분

문제 성공 여부 : 성공

 

 

접근 방법(비이상적인 버전) :

  1. 먼저 문제를 해결하는 방법은 매우 간단하다.
  2. {2}, {2,1}, {2,1,3} 이렇게 집합이 주어질 때, 가장 작은 집합{2}부터 다음으로 큰 집합에 처음으로 등장하는 수가 원본 튜플의 순서가 된다.
  3. 쉽게 말해 2가 제일 처음 나왔으니 원본 튜플에 2가 가장 먼저오고, 다음 {2,1}에 처음 오는 수가 1이니 원본 튜플은 [2,1]이 된다.
  4. 하지만 이 문제는 {2}, {2,1}, {2,1,3} 이런 숫자 집합을 어떻게 추출하느냐에 더 어려움을 겪었다.
import java.util.*;
class Solution {
    public int[] solution(String s) {
        List<String> list = new ArrayList<>();
        s = s.substring(1,s.length()-1); // 일단 제일 처음과 끝 { } 삭제
        
        
        Stack<Character> stack = new Stack<>();
        String string = "";
        int cnt = 0;
        for(int i =0; i<s.length(); i++){
            char c = s.charAt(i);
            
            if(c == '{'){ 
                stack.push(c);
            }
            else if(c == '}'){ // 집합 별로 list에 저장
                stack.pop();
                list.add(string);
                string = "";
                i++;
                cnt++; // 집합의 개수
            }
            else{
                string += c; // 2,1,3,... 을 string에 저장
            }
        }
        
        // 결과적으로 list에 {2}, {2,1}, {2,1,3}, ... 이 저장된다
        
        List<Integer>[] arr = new ArrayList[cnt]; // 각 인덱스 별로 하나의 집합에 해당하는 수 저장
        for(int i = 0; i<arr.length; i++) arr[i] = new ArrayList<>();
        
        int idx = 0;
        for(String ss : list){
            StringTokenizer st = new StringTokenizer(ss, ","); // 집합 내에 ","를 기준으로 숫자를 추출한다.
            while(st.hasMoreTokens()){
                int num = Integer.parseInt(st.nextToken()); // Integer로 변환시켜 arr에 추가한다
                arr[idx].add(num);
            }
            idx++;
        }
        
        Arrays.sort(arr, (o1, o2) -> { // 집합의 크기가 작은 순(원소가 적은 순)으로 정렬한다.
            return o1.size() - o2.size();
        });
        
        
        HashSet<Integer> hs = new HashSet<>();
        int[] ans = new int[cnt];
        idx = 0;
        for(int i =0; i<cnt; i++){ 
            for(int j =0; j<arr[i].size(); j++){
                int num = arr[i].get(j);
                if(!hs.contains(num)){ // 해시셋을 통해 존재하지 않는 수는 ans에 추가하고 hs에도 추가한다.
                    ans[idx++] = num;
                    hs.add(num);
                }
            }
        }
            
        return ans;
    }
}

 

ㅋㅋㅋㅋㅋㅋ........................

풀면서도 느꼈는데 정리하면서 보니 너무너무너무 무식한 방법으로 문제를 해결한 것 같다..

시간을 재면서 풀었기에 조급한 마음에 코드를 쓴 탓도 있지만, String 메서드에 대한 무지함이 한몫한 것 같다..

 

 

 

접근 방법(이상적인 버전) :

  1.  String 메서드 중 split이라는 것이 있었다. 원하는 문자열 단위로 String 배열에 분리할 수 있다.
  2. 제일 처음 {{와 }}를 빼고, },{ 단위로 숫자들을 분리하면 2  2,1,3   2,3 이렇게 집합을 쉽게 분리할 수 있다.

전체 코드(성공) :

import java.util.*;
class Solution {
    public int[] solution(String s) {
        s = s.substring(2,s.length()-2); // {{, }} 제거
        String[] s_arr = s.split("\\},\\{"); // 이스케이프를 통해 },{를 기준으로 split한다.

        Arrays.sort(s_arr, (o1,o2) -> { // 문자열 길이를 기준으로 정렬한다
            return o1.length() - o2.length();
        });
        
        HashSet<String> hs = new HashSet<>();
        int[] ans = new int[s_arr.length];
        
        int idx = 0;
        for(String ss: s_arr){
            String[] temp = ss.split(","); // 한 집합에 대해 각 숫자들을 분리한다.
            
            for(String num: temp){
                if(!hs.contains(num)){ // 셋에 없을 경우 추가한다
                    ans[idx++] = Integer.parseInt(num);
                    hs.add(num);
                }
            }
        }
        
        return ans;
    }
}

 

다른 고수분들의 코드에 비해서는 아직 지저분하지만, 내 코드 스타일이 반영된 만족스러운 코드인 것 같다.