본 캠프

리액트 주특기 플러스. (8)

Iruka913 2024. 12. 18. 20:53

신나는 알고리즘 풀이 시간. 

문제 설명

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.

  • 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
    • 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
    • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
  • k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
    • 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.

이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.

문제 설명

무지가 개발하려는 신고 처리 시스템의 동작은 다음과 같다:

  1. 유저는 다른 유저를 신고할 수 있다.
  2. 중복 신고는 1회로 처리한다.
  3. 특정 유저가 k번 이상 신고를 받으면 계정이 정지된다.
  4. 정지된 유저를 신고한 유저는 정지 사실을 메일로 통보받는다.
  5. 모든 처리는 신고 내용을 한꺼번에 취합한 뒤 실행된다.

문제 풀이

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. 배운 점

  1. Set의 활용
    • 중복을 방지할 때 Set 자료구조를 사용하는 것이 매우 유용하다.
  2. 객체(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