본문 바로가기
프로그래머스

프로그래머스 lv2 - 뉴스 클러스터링 (자바) [2018 KAKAO BLIND RECRUITMENT]

by dragonDeok 2024. 6. 15.
728x90

문제


프로그래머스 lv2 - 뉴스 클러스터링

풀이


교집합과 합집합을 구하는 로직이 중요

주의할 점

집합 문제에서 java에서 제공하는 교집합 함수인 List.retainAll() 사용은 지양하자.
테스트 케이스는 통과하더라도 예상치 못한 계산이 될 수 있는 가능성이 있다.

위 로직만 생각해낸다면 충분히 풀 수 있는 문제이다.

어려웠던 점


  • 처음 풀이 방법으로 java의 List 컬렉션의 retainAll()을 이용해 교집합을 구했다.
  • retainAll()은 더 작거나 같은 길이의 list에서 사용해야 한다는 것을 처음 알았다.
    ex) l1.retainAll(l2); // l1의 길이가 l2보다 작거나 같은 경우
  • 하지만 위 방식으로 풀었는데도 정확성이 53점으로 실패했다.

결국 처음 풀이을 완전히 뒤엎고 교집합, 합집합 구하는 걸 직접 구현했다.
-> 이 방법을 생각해내지 못했다.

코드

import java.util.*;
class Solution {
    public static final int N = 65536;
    public int solution(String str1, String str2) {
        int answer = 0;
        ArrayList<String> l1 = new ArrayList<>();
        ArrayList<String> l2 = new ArrayList<>();

        convert(str1, l1);
        convert(str2, l2);

        if (l1.isEmpty() && l2.isEmpty())
            return N;

        ArrayList<String> g = new ArrayList<>(); // 교집합
        ArrayList<String> h = new ArrayList<>(); // 합집합

        for (String s : l1) {
            if (l2.remove(s) == true)
                g.add(s);
            h.add(s);
        }
        h.addAll(l2);

        answer = cal(g.size(), h.size());

        return answer;
    }

    void convert(String str, ArrayList<String> list) {
        str = str.toLowerCase();
        for (int i = 0; i < str.length() - 1; i++) {
            char c1 = str.charAt(i);
            char c2 = str.charAt(i + 1);
            if (('a' <= c1 && c1 <= 'z') && ('a' <= c2 && c2 <= 'z'))
                list.add(String.valueOf(c1) + String.valueOf(c2));
        }
    }

    int cal(int in, int out) {
        double num = (double)in * N / out;
        return (int)Math.floor(num);
    }
}

참고


뉴스 클러스터링 풀이
결국 스스로 풀지 못하고 이 분의 해법을 살짝 참고했다ㅠ