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

subbni·2023년 2월 21일
0

프로그래머스

목록 보기
12/23

문제

풀이

코드를 짜기 전 손으로 짜본 로직은 다음과 같다.

  1. str1과 str2를 toUpperCase 처리한다. (case-insentive하므로)
  2. str1과 str2를 순회하며 원소를 각 Map에 넣는다
    -> 2글자씩 넣는다.
    -> 글자 중 하나라도 영문자가 아닌 경우 넣지 않는다.
    -> 이미 Map에 존재하는 key일 경우 value를 늘려준다.
  3. 두 Map 중 하나를 기준으로 순회한다.
    if(다른 Map에 존재)
    더 큰 value를 합집합에 더하기
    더 작은 value를 교집합에 더하기
    Map에서 해당 key 삭제
    else 합집합에 해당 value 더하기
  4. 나머지 Map에 원소가 남아있다면 맵을 순회하며 해당 value들을 합집합에 더하기
  5. return 교집합/합집합*65536

그리고 실제로 짠 코드

코드

import java.util.HashMap;
class Solution {
    public int solution(String str1, String str2) {

        str1 = str1.toUpperCase();
        str2 = str2.toUpperCase();
        HashMap<String,Integer> str1Map = new HashMap<>();
        HashMap<String,Integer> str2Map = new HashMap<>();
        
        for(int i=0;i<str1.length()-1;i++) {
            if((str1.charAt(i)>='A'&& str1.charAt(i)<='Z')&&(str1.charAt(i+1)>='A'&& str1.charAt(i+1)<='Z')) {
                str1Map.put(str1.substring(i, i+2),str1Map.getOrDefault(str1.substring(i,i+2),0)+1);
            }
        }
        for(int i=0;i<str2.length()-1;i++) {
            if((str2.charAt(i)>='A'&& str2.charAt(i)<='Z')&&(str2.charAt(i+1)>='A'&& str2.charAt(i+1)<='Z')) {
                str2Map.put(str2.substring(i,i+2),str2Map.getOrDefault(str2.substring(i,i+2),0)+1);
            }
        }

        if(str1Map.isEmpty() && str2Map.isEmpty()) return 65536;
        else if(str1Map.isEmpty() || str2Map.isEmpty()) return 0;
        
        int combined=0;
        int intersect=0;

        for(String key : str1Map.keySet()) {
            if(str2Map.containsKey(key)) {
                int max = Math.max(str1Map.get(key),str2Map.get(key));
                int min = Math.min(str1Map.get(key),str2Map.get(key));
                combined += max;
                intersect += min;
                str2Map.remove(key);
            } else {
                combined += str1Map.get(key);
            }
        }

        if(!str2Map.isEmpty()) {
            for(String key : str2Map.keySet()) {
                combined += str2Map.get(key);
            }
        }
        
        double answer = (double)intersect/(double)combined;
        return (int)(answer*65536);
    }
}

처음 코드를 제출했을 때 테스트 케이스 하나에 실패했다.
당시 Map이 비어있을 경우를

		if(str1Map.isEmpty() && str2Map.isEmpty()) return 65536;

이 문장 하나로 처리했었다.

두 집합이 모두 공집합인 경우 자카드 유사도는 1로 정의한다. 라는 문제 설명에 의해 처리된 문이다.
그렇지만 두 집합 중 하나만이 공집합인 경우엔 자카드 유사도가 0/n (n>0)로 0이 되므로 0*65536=0의 처리를 해주어야 한다.

        if(str1Map.isEmpty() && str2Map.isEmpty()) return 65536;
       else if(str1Map.isEmpty() || str2Map.isEmpty()) return 0;

else if문으로 이를 처리해준 뒤 제출하자 모든 케이스에서 통과가 되며 문제 제출이 완료되었다!

profile
개발콩나물

0개의 댓글