이 문제의 핵심은 어떻게 가장 빠르게 두 집합 간 교집합의 갯수와 합집합의 갯수를 구하느냐이다.
이 문제에는 조건이 있다. 집합 안의 원소들은 모두 길이가 2인 영어로만 구성된 문자열이라는 것이다.
또한, 문자열 간 비교시 대소문자 관계를 신경 쓰지 않는다고 했다.
따라서, a를 A라고 생각해도 된다는 것임.
그러면, 문제가 매우 간단해진다. 어차피 길이는 2인 문자열이므로, 2차원 배열로 26*26의 공간을 만들고 해당하는 문자열의 갯수를 세주면 된다.
이후, 교집합을 구할 때는 26 x 26 번 순회를 하면서 둘 중 더 작은 갯수로, 합집합을 구할때는 둘 중 더 큰 갯수로 더해주면 된다.
import java.util.*;
class Solution {
int interCount = 0;
int unionCount = 0;
int[][] count1 = new int[26][26];
int[][] count2 = new int[26][26];
public int solution(String str1, String str2) {
int count1Size = initCount(str1, count1);
int count2Size = initCount(str2, count2);
if (count1Size == 0 && count2Size == 0) {
return 65536;
}
countInter(count1Size, count2Size);
countUnion();
double result = (double)interCount / unionCount;
result*=65536;
return (int)result;
}
int initCount(String s, int[][] count) {
int size = 0;
for(int i=0; i<s.length()-1; i++) {
if(isEnglish(s.charAt(i)) && isEnglish(s.charAt(i+1)) ) {
int x = (s.charAt(i) >= 65 && s.charAt(i) <= 90) ? s.charAt(i)-65 : s.charAt(i) -97;
int y = (s.charAt(i+1) >= 65 && s.charAt(i+1) <= 90) ? s.charAt(i+1)-65 : s.charAt(i+1) -97;
count[x][y]++;
size++;
}
}
return size;
}
void countInter(int s1Size, int s2Size) {
if (s1Size == 0 || s2Size == 0) {
interCount = 0;
return;
}
for (int i = 0; i<26; i++) {
for (int j=0; j<26; j++) {
interCount += Math.min(count1[i][j], count2[i][j]);
}
}
}
void countUnion() {
for (int i = 0; i<26; i++) {
for (int j=0; j<26; j++) {
unionCount+=Math.max(count1[i][j],count2[i][j]);
}
}
}
boolean isEnglish(char c) {
return (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ;
}
}
