💡Problem Solving/Programmers

[프로그래머스] 뉴스 클러스터링 (Java)

gom20 2021. 10. 23. 13:05

#문제

https://programmers.co.kr/learn/courses/30/lessons/17677

 

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

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

programmers.co.kr


#풀이

1. 각 문자열을 두 문자씩 쪼개서 Map<String, Integer>에 넣는다. 이때 value값은 해당 문자가 나온 횟수이다. 

- 정규식을 이용해 특수문자가 포함된 문자를 필터링한다. 

- 이 때 원소의 총 개수를 count한다. 

 

2. 교집합의 개수를 구한다.

- 둘 중 하나의 맵을 순회하면서 다른 맵의 동일한 key가 있는지 체크하여, 동일한 key가 있으면 value의 Min값의 합을 구한다. 

 

3. 합집합의 원소를 구한다.

- 전체 원소 개수 - 교집합 원소 개수

- 합집합이 공집합일 경우 65536 리턴한다.

- 이 외 케이스는 자카드 유사도 계산하여 리턴한다.

 

Java 정규식에서 영문자 이외에 모든 문자를 제거하고 싶을 때는 [^A-Za-z] 괄호 안에 ^ 기호를 붙여서 사용한다. 

괄호 밖에 있으면 첫번째 등장하는 조건이니 유의해야한다.

 

#소스코드

import java.util.*;
import java.util.regex.*;
class Solution {
    public HashMap<String, Integer> map1, map2;
    
    public int solution(String str1, String str2) {
        int answer = 0;
        map1 = new HashMap<String, Integer>();
        map2 = new HashMap<String, Integer>();
        str1 = str1.toUpperCase();
        str2 = str2.toUpperCase();
        
        Pattern p = Pattern.compile("[^A-Za-z]");
        Matcher m = null;
        int totalCnt = 0;
        for(int i = 0; i <= str1.length()-2; i++){
            String key = str1.substring(i, i+2);
            m = p.matcher(key);
            if(m.find()) continue;
            map1.put(key, map1.getOrDefault(key, 0) + 1);
            totalCnt++;
        }
        
        for(int i = 0; i <= str2.length()-2; i++){
            String key = str2.substring(i, i+2);
             m = p.matcher(key);
            if(m.find()) continue;
            map2.put(key, map2.getOrDefault(key, 0) + 1);
            totalCnt++;
        }
        
        int interCnt = 0;
        for(String key : map1.keySet()){
            if(map2.get(key) == null) continue;
            interCnt += Math.min(map2.get(key), map1.get(key));
        }
        
        int unionCnt = totalCnt - interCnt;
        if(unionCnt == 0) return 65536;
        return interCnt*65536/unionCnt;
    }
}