⚡문제정보
문제가 아주 깁니다만 아래를 보면 감이 오실겁니다.
요약하자면 문제는 이렇습니다.
1. string 두개가 매개변수로 들어온다.
2. 들어온 문자열은 두글자씩 끊어서 만드는데 알파벳으로된 쌍만 유효하다.
3. 대소문자는 구분하지 않는다.
4. *****다중집합을 허용한다
5. 교집합 / 합집합 * 65536을 한 값을 리턴해라
6. 만약 교집합도 없고 합집합도 없다면 1 * 65536을 리턴해라
🔍접근방법
1. 우선 알파벳쌍만 유효하게 처리하기 때문에 알파벳이 아닌 값들을 걸러줄 정규표현식이 있으면 좋겠습니다.
2. 교집합과 합집합을 구현해야 합니다.
3. 다중집합을 고려해야합니다 따라서 자바스크립트의 set을 사용하는데에는 제한사항이 있습니다.
set은 중복을 허용하지 않기 때문입니다.
4. 따라서 어쩔수없이 Map을 이용해서 동일한 단어의 등장횟수까지 카운트해줍니다.
5. 교집합,합집합이 없는 케이스를 고려한 예외문을 만듭니다.
🔍나의 풀이
function solution(str1, str2) {
function maker(str) {
let map = new Map()
let eng = /[a-z]/ig;
for(i=0; i<str.length-1; i++) {
let reg = (str[i] + str[i+1]).match(eng);
let setter = reg?.join('').toUpperCase()
if(setter?.length == 2) {
map.set(setter , (map.get(setter) || 0 ) +1)
}
}
return map
}
function union (mapA , mapB) {
let dupmap = new Map(mapB)
mapA.forEach( (value,key) => {
if(mapB.has(key)) {
dupmap.set(key , Math.max(mapB.get(key) , mapA.get(key)) )
}
else {
dupmap.set(key, mapA.get(key))
}
})
return [...dupmap].reduce((acc,cur) => { return acc + cur[1] },0)
}
function intersect (mapA, mapB) {
let result = 0
mapA.forEach( (value,key) => {
if(mapB.has(key)) {
result += Math.min(mapB.get(key) , mapA.get(key))
}
})
return result
}
let [map1 , map2] = [maker(str1),maker(str2)]
if(map1.size == 0 && map2.size == 0) return 65536
if(map1.size == 0 || map2.size == 0) return 0
let [uni, inter ] = [union(map1,map2) , intersect(map1,map2)]
return Math.floor( (inter / uni) * 65536 )
}
전 함수를 여러개 만들어서 문제를 풀었습니다.
문자쌍을 만들어줄 maker 함수와
합집합을 구현할 union 함수
교집합을 구현할 intersect 함수입니다.
set으로 합집합,교집합을 구현한 코드들은 많은데
map으로는 검색해도 안나오길래 그냥 제 나름대로 구현했습니다.
🔍 Maker함수 설명
function maker(str) {
let map = new Map()
let eng = /[a-z]/ig;
//정규표현식으로 [a-z] 알파벳만 서칭하는데 i는 대소문자를 구분하지 않는다는 뜻입니다.
//만약 i를 빼고 쓰고싶다면 /[a-zA-Z]/로 많이 사용하시는것같습니다.
for(i=0; i<str.length-1; i++) {
let reg = (str[i] + str[i+1]).match(eng);
// 변수를 선언하고 문자를 두개씩 담은 뒤 match 메서드를 이용해
// 정규표현식에 매칭되는 문자들만 남겨줍니다.
// match메서드는 정규표현식 규칙에 맞는 문자들만 담은 배열을 반환합니다.
let setter = reg?.join('').toUpperCase()
// ?. 옵셔널체이닝 연산자를 사용해야하는 이유는
// 만일 match 메서드과정에서 알파벳이 없는 케이스를 만났을 경우 null이 반환됩니다.
// null에는 join 메서드, toUpperCase()메서드를 사용할 수 없기 때문에
// 에러가 발생합니다. 따라서 옵셔널 체이닝 연산자로
// undefined, null 케이스가 아닐때만 join('')을 실행시켜주는 코드입니다.
if(setter?.length == 2) {
map.set(setter , (map.get(setter) || 0 ) +1)
}
//만약 setter의 길이가 2라면 str[i] 와 str[i+1]이 모두 알파벳이라는 뜻이니
//map에 set해줍니다.
}
return map
}
🔍Union 함수 설명
function union (mapA , mapB) {
let dupmap = new Map(mapB)
// mapB를 복사해줍니다.
// 만약 이 과정을 생략하고 mapB를 바로 수정해버리면
// 참조에 의한 값 변경이 일어나며 매개변수로 넘겨준 map또한 수정되어버립니다.
// 이를 막기 위해 map을 복사해서 새로운 변수에 할당해줍니다.
mapA.forEach( (value,key) => {
if(mapB.has(key)) {
dupmap.set(key , Math.max(mapB.get(key) , mapA.get(key)) )
}
else {
dupmap.set(key, mapA.get(key))
}
// 만약 mapA의 key를 mapB도 가지고 있다면 그 둘은 같은 key를 갖고있다는 뜻입니다.
// union 함수에서는 합집합을 구현하고있기때문에 둘중 밸류가 높은 값을 할당해줍니다.
// 생각해보니까 mapA.get(key)는 할 필요가 없고 그냥 value를 써도 무방합니다.
// map 자료구조에 forEach를 하면 value,key순으로 매개변수가 들어옵니다.
})
return [...dupmap].reduce((acc,cur) => { return acc + cur[1] },0)
// 이터러블인 map을 전개연산자로 배열로 만들어 준뒤
// 배열메서드 reduce를 이용해 밸류값을 카운팅해줍니다.
}
🔍intersect 함수 설명
function intersect (mapA, mapB) {
let result = 0
mapA.forEach( (value,key) => {
if(mapB.has(key)) {
result += Math.min(mapB.get(key) , mapA.get(key))
}
// 교집합을 구현합니다.
// 만약 mapA에도 존재하는 key가 mapB에도 존재한다면 그 둘은 교집합입니다.
// 둘 중 더 작은 밸류를 result에 추가해주면 result가 곧 둘의 교집합 갯수입니다.
})
return result
}
let [map1 , map2] = [maker(str1),maker(str2)]
// 비구조화할당으로 map1, map2에 maker함수의 반환 결과를 할당해줍니다.
if(map1.size == 0 && map2.size == 0) return 65536
if(map1.size == 0 || map2.size == 0) return 0
//예외 케이스를 처리해줍니다.
let [uni, inter ] = [union(map1,map2) , intersect(map1,map2)]
// 위 코드와 마찬가지인데 교집합, 합집합을 구현하는 함수의 반환 결과를 할당해줍니다.
return Math.floor( (inter / uni) * 65536 )
// 문제조건에 맞춰 답을 반환합니다.
// 문제조건은 소숫점을 버리고 65536을 곱하라는 내용이었습니다.
다른 사람의 풀이를 보니까 저같이 맵을 써서 푼 사람들은 거의 안보이네요
사람들이 이렇게 생각하는게 다르구나 ㄹㅇㅋㅋ
반응형
'programmers' 카테고리의 다른 글
[Programmers Level 1] 덧칠하기 Javascript (0) | 2023.03.22 |
---|---|
[Programmers Level 1] 바탕화면 정리 Javascript (0) | 2023.03.05 |
[Programmers Level 3] 야근지수 Javascript (0) | 2023.01.12 |
[Programmers Level 2] 스킬트리 Javascript (0) | 2023.01.11 |
[Programmers Level 1] 개인정보 수집 유효기간 Javascript (0) | 2023.01.11 |