신나는 알고리즘 풀이 시간.
문제 설명
신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.
- 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
- 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
- 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
- k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
- 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.
이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.
문제 설명
무지가 개발하려는 신고 처리 시스템의 동작은 다음과 같다:
- 유저는 다른 유저를 신고할 수 있다.
- 중복 신고는 1회로 처리한다.
- 특정 유저가 k번 이상 신고를 받으면 계정이 정지된다.
- 정지된 유저를 신고한 유저는 정지 사실을 메일로 통보받는다.
- 모든 처리는 신고 내용을 한꺼번에 취합한 뒤 실행된다.
문제 풀이
1. 요구사항 분석
- 중복 신고를 제거해야 하므로, Set 자료구조를 사용해 중복을 방지.
- 각 유저가 신고한 유저와 신고받은 횟수를 효율적으로 관리하기 위해 객체(Map 형태) 사용.
- 정지된 유저의 목록을 추출하고, 이를 기반으로 각 유저가 받을 메일의 수를 계산.
function solution(id_list, report, k) {
let answer = [];
let reportedCount = {};
const userReports = {};
id_list.forEach((id) => {
userReports[id] = [];
});
const reportSet = new Set(report);
reportSet.forEach((report) => {
const splitedArray = report.split(" ");
const reporter = splitedArray[0];
const bad = splitedArray[1];
if (!reportedCount[bad]) {
reportedCount[bad] = 1;
} else {
reportedCount[bad] += 1;
}
userReports[reporter].push(bad);
});
const bannedUsers = Object.keys(reportedCount).filter(
(user) => reportedCount[user] >= k
);
const answerArray = new Array(id_list.length).fill(0);
id_list.forEach((user, idx) => {
userReports[user].forEach((reported) => {
if (bannedUsers.includes(reported)) {
answerArray[idx] += 1;
}
});
});
return answerArray;
}
2. 풀이 단계
1) 중복 신고 제거
Set을 사용해 동일한 신고를 한 번만 처리:
const reportSet = new Set(report);
2) 신고 내역 기록
신고한 유저와 신고받은 유저를 객체에 기록:
reportSet.forEach((report) => {
const splitedArray = report.split(" ");
const reporter = splitedArray[0];
const bad = splitedArray[1];
if (!reportedCount[bad]) {
reportedCount[bad] = 1;
} else {
reportedCount[bad] += 1;
}
userReports[reporter].push(bad);
});
3) 정지된 유저 추출
신고 횟수가 k 이상인 유저를 필터링:
const bannedUsers = Object.keys(reportedCount).filter(
(user) => reportedCount[user] >= k
);
4) 메일 수 계산
각 유저가 신고한 유저 중 정지된 유저의 수를 계산:
id_list.forEach((user, idx) => {
userReports[user].forEach((reported) => {
if (bannedUsers.includes(reported)) {
answerArray[idx] += 1;
}
});
});
3. 배운 점
- Set의 활용
- 중복을 방지할 때 Set 자료구조를 사용하는 것이 매우 유용하다.
- 객체(Map)의 활용
- 데이터를 효율적으로 관리하고, 유저별로 신고 내역을 기록하는 데 적합하다.
결론
이번 문제는 효율적인 데이터 처리와 조건 검증이 중요한 문제였다.
Set과 객체를 활용해 데이터를 구조화하고, 각 유저의 메일 수를 계산하는 과정에서 많은 것을 배울 수 있었다.
앞으로도 더 복잡한 문제를 풀며 효율적인 코드를 작성하는 연습을 지속하고 싶다.
'본 캠프' 카테고리의 다른 글
리액트 심화 프로젝트 (1) (3) | 2024.12.20 |
---|---|
리액트 주특기 플러스. (9) (1) | 2024.12.19 |
리액트 주특기 플러스. (7) (2) | 2024.12.17 |
리액트 주특기 플러스. (6) (0) | 2024.12.16 |
리액트 주특기 플러스. (6) (1) | 2024.12.13 |