알고리즘/프로그래머스 카카오

프로그래머스 Lv.2) [1차] 뉴스 클러링

Zin0_0 2020. 5. 22. 22:47
반응형

2018 KAKAO BLIND RECRUITMENT [1차]

뉴스 클러링

 

코딩테스트 연습 - [1차] 뉴스 클러스터링

뉴스 클러스터링 여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브��

programmers.co.kr

풀이

한 index를 기준으로 다음 Index와 합쳐 하나의 집합을 이루는데, 이 때 알파벳인지를 확인하는 것과 다중집합이 가능하다는 점, 대소문자 차이는 무시하고 같은 원소로 취급한다는 점, 합집합이 0일 때는 1을 리턴한다 이 4가지만 유의하면 되는 문제다.

처음에 알파벳 집합만 가능하다에서 알파벳을 제외한 글자는 제거하고 집합을 구해줬더니, 생기면 안되는 집합이 생기는 문제가 있었다.

그래서 index를 각각 돌면서 체크하는 방식으로 바꿔주었다.

그 다음에는 다중집합이 가능하다에서 어떻게 해야하는지 고민이 많았다. 그래서 문자열에 대해 각각 HashMap을 만들어서 두글자로 만들어진 집합에 대해 각각 몇 개인지 체크했다.

이후 발생한 문제는 합집합이 0인 경우였다. 답을 double형으로 구하고 int형으로 형 변환을 할 때 가지는 문제를 제대로 핸들링하지 못했었다. 그래서 그냥 합집합의 총 개수를 세주어 0개일 때, 유사도를 1로 설정해주어 문제를 풀었다.

 

로직

1. 문자열 str1,과 str2에 대해 각각 집합을 구해준다.

 1-1. 각각 집합을 구할 때, 다중 집합을 고려해 HashMap을 통해 해당 부분 집합이 몇 번 등장하는지 저장해줬다.

2. 두 문자열의 집합들에 대해 합집합과 교집합을 구해준다.

3. 합집합과 교집합을 구한다.

 3-1. 이 때, 합집합과 교집합의 수를 각각 연산한다.

 3-2. 합집합이 0이라면 유사도는 1로 세팅한다.

4. 유사도에 65536을 곱한 후, int형으로 리턴한다.

 

코드

import java.util.ArrayList;
import java.util.HashMap;

class Solution {
    final static int MULTIPLYING = 65536;
    public int solution(String str1, String str2) {
        return getSimilarity(str1, str2);
    }
    
    private int getSimilarity(String str1, String str2) {
        ArrayList<String> str1List = makeUnion(str1);
        ArrayList<String> str2List = makeUnion(str2);

        HashMap<String,Integer> str1Map = new HashMap();
        HashMap<String,Integer> str2Map = new HashMap();

        ArrayList<String> unionList = new ArrayList<>();
        ArrayList<String> intersectionList = new ArrayList<>();

        setLists(str1List,str1Map,str2List,unionList,intersectionList);
        setLists(str2List,str2Map,str1List,unionList,intersectionList);

        int union = 0;
        for(String str : unionList) {
            if(str1Map.containsKey(str)) { // 1만
                if(str2Map.containsKey(str)) {  // 둘 다
                    union += Math.max(str1Map.get(str),str2Map.get(str));
                } else {
                    union += str1Map.get(str);
                }
            } else if(str2Map.containsKey(str)) { // 2만
                union += str2Map.get(str);
            }
        }
        int intersection =0;
        for(String str : intersectionList) {
            intersection += Math.min(str1Map.get(str), str2Map.get(str));
        }
        double similiarity = (double)intersection/union;
        if(union ==0) { // 합집합이 0인 경우
            similiarity =1.0;
        }

        similiarity *= MULTIPLYING;
        return (int)(similiarity);
    }
    
    private static void setLists(ArrayList<String> origin, HashMap<String, Integer> strMap,ArrayList<String> target, ArrayList<String> unionList, ArrayList<String> intersectionList) {
        for(String str : origin) {
            if(!unionList.contains(str)) {
                unionList.add(str);
            }
            if(!intersectionList.contains(str) && target.contains(str)) {
                intersectionList.add(str);
            }
            if(!strMap.containsKey(str)) {
                strMap.put(str,1);
            } else {
                strMap.replace(str, strMap.get(str)+1);
            }
        }
    }
    
    private ArrayList<String> makeUnion(String str) {
        ArrayList<String> result = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        
        for(int i=0; i<str.length()-1; i++) {
            char left = str.charAt(i);
            char right = str.charAt(i+1);
            
            if(isChar(left) && isChar(right)) { // 글자
                if(left >=97) { // 소문자 -> 대문자
                    left-=32;
                }
                if(right >=97) {// 소문자 -> 대문자
                    right-=32;
                }
                sb.append(left).append(right);
                result.add(sb.toString());
                sb.setLength(0);
            }
            
        }
        return result;
    }
    
    private boolean isChar(char ch) {
        return (ch >=65 && ch<=90) || (ch>=97 && ch<=122) ? true : false;
    }
}
반응형