코테 준비

[프로그래머스 - 카카오] 튜플 - Java

우디혜 2020. 10. 20. 17:32

programmers.co.kr/learn/courses/30/lessons/64065

 

코딩테스트 연습 - 튜플

"{{2},{2,1},{2,1,3},{2,1,3,4}}" [2, 1, 3, 4] "{{1,2,3},{2,1},{1,2,4,3},{2}}" [2, 1, 3, 4] "{{4,2,3},{3},{2,3,4,1},{2,3}}" [3, 2, 4, 1]

programmers.co.kr

로직은 쉬웠지만... 자바로 문자열 처리하는게 오랜만이라 시간이 좀 걸렸다.

 

로직

#2 코드 로직으로 적겠다.

  1. s는 하나의 스트링형태로 되어있기 때문에 "{"와 "}"를 모두 제거하고, ","를 기준으로 분할하여 숫자들만 모아 하나의 list로 만든다.

  2. 숫자를 카운트 하여 카운트 정보를 Hashtable에 넣어준다(Hashtable<숫자, 카운트된 횟수>). 

  3. 최종 리턴 값은 카운트된 횟수 기준으로 내림차순 정렬이 되어야하기 때문에 Hashtable을 순회하면서 (Hashtable 전체 길이 - 카운트된 횟수)를 index로하여 최종 리턴 리스트 answer에 숫자를 넣어준다.

    • 예를 들면 s = "{{2},{2,1},{2,1,3},{2,1,3,4}}" 일 경우 hashtable의 길이는 4가 된다(숫자가 4종류이므로). 그리고 가장 카운트 횟수가 많은 2는 총 4번 출현하게 되고 가장 앞에 와야하기 때문에 index = 4 - 4 = 0이 된다.

 

코드

# 1

import java.util.*;
class Solution {
    public int[] solution(String s) {
        // make a dictionary for integer frequency
        Hashtable<Integer, Integer> dictionary = new Hashtable<Integer, Integer>();
        make_dictionary(dictionary, s.split("}"));
        
        // initalize answer list with dictionary size
        int N = dictionary.size();
        int[] answer = new int[N];
        
        // fill out the answer list with dictionary
        for(Integer key : dictionary.keySet()){
            int index = N - dictionary.get(key);
            answer[index] = key;
        }
        
        return answer;
    }
    
    void make_dictionary(Hashtable<Integer, Integer> dictionary, String[] s){
        for(String str : s){
            for(String str_num : str.split(",")){
                String tmp = str_num.replaceAll("\\{", "");
                if(tmp.matches("([^\\s][0-9]*)")){
                    int num = Integer.parseInt(tmp);
                    int count = dictionary.getOrDefault(num, 0);
                    dictionary.put(num, count + 1);
                }
            }
        }
    }
    
      void print_dictionary(Hashtable<Integer, Integer> dictionary){
        Set<Integer> keys = dictionary.keySet();
        for(Integer key : keys){
            System.out.println(key + " : " + dictionary.get(key));
        } 
        System.out.println(" ");
    }
}

처음 썼던 코드... ㅎ 문자열 처리하는 부분이 살짝 더럽다...

가령 s = "{{2},{2,1},{2,1,3},{2,1,3,4}}" 일 경우 위의 코드는 첫 번쨰 for문에서 {2} {2,1} {2,1,3} {2,1,3,4} 단위로 벗겨낸 뒤 , 두 번째 for문에서 2 카운트, 2 1 카운트, 2 1 3 카운트... 이런 느낌이다.

 

사실 코드를 쓰는 중간 즈음에 그냥 다 잘라서 숫자 카운트 하면 된다는 걸 이중 for문을 쓰다가 알아버림.. 게다가 replaceAll()안에 여러 개의 패턴을 쓸 수 있다는 사실도 몰랐기 때문에 제출 이후 좀 더 깔끔하게 정리해보았다.

 

 

# 2

import java.util.*;
class Solution {
    public int[] solution(String s) {
        // make a dictionary for integer frequency
        Hashtable<Integer, Integer> dictionary = new Hashtable<Integer, Integer>();
        make_dictionary(dictionary, s.replaceAll("[}{]", "").split(","));
        
        // initalize answer list with dictionary size
        
        int N = dictionary.size();
        int[] answer = new int[N];
        
        // fill out the answer list with dictionary
        
        for(Integer key : dictionary.keySet()){
            int index = N - dictionary.get(key);
            answer[index] = key;
        }
        return answer;
    }
    
    void make_dictionary(Hashtable<Integer, Integer> dictionary, String[] s){
        for(String str : s){
            if(str.matches("[^\\s]*")){
                int num = Integer.parseInt(str);
                int count = dictionary.getOrDefault(num, 0);
                dictionary.put(num, count + 1);
            }
        }
    }
    
      void print_dictionary(Hashtable<Integer, Integer> dictionary){
        Set<Integer> keys = dictionary.keySet();
        for(Integer key : keys){
            System.out.println(key + " : " + dictionary.get(key));
        } 
        System.out.println(" ");
    }
}

 

#1와 비교해서 가장 큰 차이는 

  1. make_dictionary()에 들어가기 전, replaceAll("[}{]")로 "{" 와 "}" 문자열을 제거해주고 split(",")으로 "," 기준 모든 스트링(스트링화된 숫자)들을 분할하여 하나의 리스트 안에 넣어주어 문자열 처리과정을 한 코드로 정리하였다.

  2. 모든 숫자들을 하나의 리스트 안에 넣고 한 번에 처리할 수 있게 만들어서 for문이 하나로 줄었다. 아아싸

 

참고 할 것!! 
🧡 Integer.parseInt vs Integer.valueOf

parseInt vs valueOf [참고]
💛 s.split(), s.trim(), s.replaceAll()

[구글링하면 다 나옴]
💚 Hashtable

Hashtable 오라클 공식 문서 [참고]
💙 java regex 정리
- import java.util.regex.Pattern → Pattern.matches(pattern, str);
- import java.util.* → str.matches(pattern);
- regex meta character에 있는 문자의 경우({}, [], s, +, ...) \\를 붙여 사용한다. 예를들면 문자 "{" 는 "\\{" 로 패턴에 넣어주어야 한다. 삽질한 이유 중 하나 

regex 패키지 설명 [참고]

regex에서 meta character 포함된 문자 처리 방법 (stackoverflow) [참고2]
💜 java가 String을 처리하는 법

introduction to String handling (자바의 전반적인 String 특징)[참고]