코드를 짜기 전 손으로 짜본 로직은 다음과 같다.
- str1과 str2를 toUpperCase 처리한다. (case-insentive하므로)
- str1과 str2를 순회하며 원소를 각 Map에 넣는다
-> 2글자씩 넣는다.
-> 글자 중 하나라도 영문자가 아닌 경우 넣지 않는다.
-> 이미 Map에 존재하는 key일 경우 value를 늘려준다.- 두 Map 중 하나를 기준으로 순회한다.
if(다른 Map에 존재)
더 큰 value를 합집합에 더하기
더 작은 value를 교집합에 더하기
Map에서 해당 key 삭제
else
합집합에 해당 value 더하기- 나머지 Map에 원소가 남아있다면 맵을 순회하며 해당 value들을 합집합에 더하기
- 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문으로 이를 처리해준 뒤 제출하자 모든 케이스에서 통과가 되며 문제 제출이 완료되었다!