[Programmers]-뉴스 클러스터링
문제
문제 요약
문자열 str1을 두글자씩 끊어서 집합의 원소로 만든다. 나눠진 두글자는 영문자만 유효하다. 대소문자 구분없다. 나머지(공백, 특수문자, 숫자)는 버린다. A집합 B집합의 교집합 / 합집합 = 자카드 유사도다. A집합 B집합 각 원소가 0 일경우 자카드 유사도는 1이다. 출력은 (자카드 유사도 X 65536) 이다.
코드
import java.util.*;
class Solution {
public int solution(String str1, String str2) {
int answer = 0;
HashMap<Integer, String> hs1 = new HashMap<Integer, String>();
HashMap<Integer, String> hs2 = new HashMap<Integer, String>();
str1 = str1.toUpperCase(); // 대소문자 구분이 필요없어서
str2 = str2.toUpperCase(); // 둘다 대문자로 설정
int key1 = 0; // 그룹 a 원소 수
int key2 = 0; // 그룹 b 원소 수
String pattern = "^[A-Z]*$"; //regex
System.out.println(str1);
System.out.println(str2);
String subs1;//2개씩 나눈 값 저장공간
for(int i=0;i<str1.length()-1;i++){//2개씩 나눠 맵에 넣기
subs1 = str1.substring(i,i+2);
if(subs1.matches(pattern)) hs1.put(key1++, subs1);
}
String subs2;
for(int i=0;i<str2.length()-1;i++){
subs2 = str2.substring(i,i+2);
if(subs2.matches(pattern)) hs2.put(key2++, subs2);
}
int inter = 0; //교집합 수
if(key1 == 0 && key2 ==0) return 65536;
for(int i=0;i<key1;i++){//비교
for(int j=0;j<key2;j++){
if(hs1.get(i).equals(hs2.get(j))){ // 비교해서 같을경우
hs2.remove(j); // 다중중복을 없애기위해 집합B 삭제
inter++;
break;
}
}
}
key1 -= inter;
key2 -= inter;
float v = 65536*((float)inter/(float)(key1+key2+inter));
return (int)v;
}
}
코드 설명
다중중복을 없애기위해 뜻이 뭐냐면.
예를들어 a = {AA, AA, AA} , b = {AA, AA}이면
비교해서 같으면 b집합 원소를 삭제하지 않을 경우
i = 0 부터 2까지 for 문이 돌고
i가 변해도 a = {AA, AA, AA} , b = {AA AA} 그대로다.
그래서 i가 2일 때에도 교집합이 되어버린다. 하지만
삭제할 경우 i = 0 일 때 : a = {AA, AA, AA} , b = {AA} i = 1 일 때 : a = {AA, AA, AA} , b = {} i = 2 일 때 : b의 값이 없어서 더이상 교집합 inter가 증가하지 않는다.
요약 포인트
- 캐스팅할 때 (Integer)가 아니다. (int)이다.
- hashMap의 value에 나눈 값을 넣는다. 중복값이 있을 수 있으니까.
- regex에 대해서 String.matches(pattern)이 있고, 패턴도 알아보자.