프로그래머스에 코딩테스트 연습 중 하나인 해시 이론을 기록해보겠따!
key: value형태로 갖는 하나의 자료구조
전화번호부같이이름: 전번
같이 key를 부르면 그 값이 나오는 것!
O(n)
이므로 탐색할 수량이 많아지면 많아질수록 오래 걸린다.O(1)
이기에 빠르고 편하다. JS에선 Object
, map
, set
등이 있다. 이번 기회에 배워보자String
을 기반으로 정보를 기록하고 관리해야할때 써야한다!프로그래머스에서 가져오는 문제들
function solution(participant, completion) {
// 이중 for문 실패 시간복잡도
// 고차함수 find
// 객체로 다 더해서 중복 되면 2, 중복 안되면 1 그래서 1만 나오게?? + reduce
// return participant.find((pre) => completion.includes(pre) !== true);
// 초기코드el
// for (let i = 0; i < completion.length; i++) {
// for (let b = 0; b < participant.length; b++) {
// if (completion[i] === participant[b]) {
// participant.splice(b, 1)
// break;
// }
// }
// return participant.join('');
// }
participant.sort();
completion.sort();
return participant.find((pre, idx) => pre !== completion[idx]);
}
O(n²)
이라 런타임 오류가 났었다.sort
로 먼저 굴려준다.(sort
는 O(N log N)
) 이름순으로 먼저 매치해준 다음 find로 해줬다. 사실 야매고 해시는 쓰지도 않았다. 이번 기회에 해보자String
이고 완주 여부를 통해 기록해야하니 해시를 써야겠다고 판단(객체데이터 자체를 써도 무방)function solution(participant, completion) {
// 3. 해시를 이용한 map
const map = new Map();
for (let i = 0; i < participant.length; i++) {
let iPart = participant[i],
iComp = completion[i];
map.set(iPart, (map.get(iPart) || 0) + 1);
map.set(iComp, (map.get(iComp) || 0) - 1);
}
for (let [a, b] of map) {
if (b > 0) {
return a;
}
}
return undefined;
}
map
을 이용해 해시로 처리, 훨씬 성능이 좋음!||
논리 연산자로 있으면 밸류가 나오게, 아니면 0 하고 1 더하고 빼서 동명이인을 걸러줬다.위장도 String 타입의 '데이터들을 기록'하고 횟수를 구한다음 입는 종류만큼 조합을 구하기 위해 곱해야하는 구조이기에 해시구조를 이용해 구하자.
우선 난 map을 썼지만 object로도 간편하게 할 수 있다.
function solution(clothes) {
/*
* 1. 형태가 map 모양이므로 걍 map에 넣어줘 활용
* 2. map에 values을 해와 map iterator를 도출하고 from으로 배열 만들기
* 3. 새 map에 종류 별로 몇개 있는지 넣기
* 4. 방정식 사용, 곱해서 결과 도출
* 4-1. 그냥 개수가 아닌 (개수+1)을 곱해주는 이유는 각 요소마다 안입는 경우의 수도 존재하기에
* 4-2. 하나도 안입는 건 안치기에 -1 꼭 해주기
*/
// 1
const clothesMap = new Map(clothes);
// 2
const kindArr = Array.from(clothesMap.values());
// 3
const kindMap = new Map();
for (let i = 0; i < kindArr.length; i++) {
kindMap.set(kindArr[i], (kindMap.get(kindArr[i]) || 0) + 1);
}
// 4
let result = 1;
for (count of kindMap.values()) {
result *= count + 1;
}
// 4-1
return result - 1;
}
function solution(clothes) {
const obj = {};
for(let i = 0; i < clothes.length; i++) {
const arr = clothes[i];
obj[arr[1]] = (obj[arr[1]] || 0) + 1;
}
for(let key in obj) {
result *= (obj[key]+1);
}
return result - 1;
}
오히려,, 기본적인 객체 데이터를 활용한 게 훨씬 보기 좋다.. 갇히지 말자
/*
* 1. 자료 만들기
* 1-1. 해시 기록: 장르, 기록횟수, 고유번호(인덱스)
* 1-2. 해시 기록: 장르별 듣는 횟수 기록하고 내림차순 정렬하기
* 2. 2번의 첫 순서의 장르와 같은 객체(1번)를 새 배열로 넣고 또 내림차순 정렬
* 3. 정렬한 걸 가지고 result에 2개씩 넣어주기
*/
function solution(genres, plays) {
// 1-1
const allRecord = genres.map((el, idx) => ({ genre: el, playCount: plays[idx], unique: idx }));
// 1-2
// const countMap = new Map();
// for (let i = 0; i < genres.length; i++) {
// const genre = genres[i];
// const play = plays[i];
// // countMap.set(genre, (countMap.get(genre) || 0) + play);
// countMap.set(genre, countMap.get(genre) ? countMap.get(genre) + play : play);
// }
const countObj = {};
for (let i = 0; i < genres.length; i++) {
const genre = genres[i];
const play = plays[i];
countObj[genre] = (countObj[genre] || 0) + play;
}
const objToArr = Object.entries(countObj);
objToArr.sort((a, b) => b[1] - a[1]);
// 2
const result = [];
objToArr.forEach((el) => {
let bestGenre = [];
for (let j = 0; j < allRecord.length; j++) {
if (el[0] === allRecord[j].genre) {
bestGenre.push(allRecord[j]);
}
}
bestGenre.sort((a, b) => b.playCount - a.playCount);
// 3
/* 런타임 에러
* for (let z = 0; z < 2; z++) {
* result.push(bestGenre[z].unique);
* }
*/
bestGenre.forEach((el, idx) => {
if (idx < 2) {
result.push(el.unique);
}
});
});
return result;
}