🔍 문제 요약
https://school.programmers.co.kr/learn/courses/30/lessons/92334
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
id_list와 신고자 id와 피신고자 id 목록이 들어있는 report가 주어지고 신고를 당한 횟수가 k 이상인 경우 정지가 된 다고 할 때 각 id_list id들이 신고해서 정지가 된 계정의 개수를 반환하는 문제
🧠 나의 접근 방식과 시행착오
21분 정도 걸린 문제. 문제가 길긴 길지만 핵심 자체는 어렵지 않은 문제라서 일단 풀긴 풀었다. 다만 이 부분도 최적화적으로 고려할 부분이 있는 문항에 변수 이름도 좀 고쳤으면 싶었다. Dictionary에 신고자 : 피신고자 리스트로 하나, 피신고자 : 신고당한 횟수로 하나를 만들어서 풀었다.
using System;
using System.Collections.Generic;
public class Solution
{
/// <summary>
/// 신고 결과 받기
/// https://school.programmers.co.kr/learn/courses/30/lessons/92334
/// </summary>
public int[] solution(string[] id_list, string[] report, int k)
{
// 신고자 : 피신고자 리스트
Dictionary<string, List<string>> singoDict = new Dictionary<string, List<string>>();
// 피신고자 : 신고당한 횟수
Dictionary<string, int> countDict = new Dictionary<string, int>();
foreach (var data in report)
{
var datas = data.Split(' ');
var idStr = datas[0];
var singoId = datas[1];
bool alreadySingo = false;
if (singoDict.ContainsKey(idStr) && singoDict[idStr] != null)
{
if (!singoDict[idStr].Contains(singoId))
{
singoDict[idStr].Add(singoId);
}
else
{
alreadySingo = true;
}
}
else if (!singoDict.ContainsKey(idStr))
{
singoDict.Add(idStr, new List<string>());
singoDict[idStr].Add(singoId);
}
if (alreadySingo)
{
continue;
}
if (!countDict.ContainsKey(singoId))
{
countDict.Add(singoId, 1);
}
else
{
countDict[singoId]++;
}
}
int[] answer = new int[id_list.Length];
for (int i = 0; i < id_list.Length; i++)
{
var id = id_list[i];
int count = 0;
if (singoDict.ContainsKey(id))
{
var singoList = singoDict[id];
if (singoList != null)
{
foreach (var idStr in singoList)
{
if (countDict[idStr] >= k)
{
count++;
}
}
}
}
answer[i] = count;
}
return answer;
}
}
/// <summary>
/// C# 7.3
/// </summary>
internal class Program
{
public static void Main(string[] args)
{
var sl = new Solution();
var id_list1 = new[] { "muzi", "frodo", "apeach", "neo" };
var report1 = new[] { "muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi" };
int k1 = 2;
var id_list2 = new[] { "con", "ryan" };
var report2 = new[] { "ryan con", "ryan con", "ryan con", "ryan con" };
int k2 = 3;
var res1 = sl.solution(id_list1, report1, k1);
var res2 = sl.solution(id_list2, report2, k2);
foreach (var item in res1)
{
Console.Write(item + ", ");
}
Console.WriteLine();
foreach (var item in res2)
{
Console.Write(item + ", ");
}
}
}
✅ 풀이 코드
막상 피드백을 받은 코드를 보니 정말 필자가 풀었던 것보다 로직적으로 깔끔하고 알아보기도 쉽게 되어있다는 것을 알았다. 일단 중요한 부분은 reportMap이 있고 신고자와 피신고자 목록이 HashSet으로 Value가 구현되어 있는 점. Add를 했을 때 HashSet의 경우 한 개만 존재하기 때문에 false 처리 된다는 점. 그렇게 해서 true인 경우에서만 reportCount (피신고자 : 횟수)를 증가시키는 점. 이 부분 반복문지 정말 깔끔하게 처리되어 있는 점을 알 수 있다. 늘 HashSet을 익숙해져야지 싶은데 잊어먹고 그냥 List로 해서 최적화를 놓치는 부분들이 많았던 듯 하다. 실제 개발에서도 HashSet은 유용하게 쓸 수 있을 것이라 생각하는 거라 잘 고민해보자
public int[] solution(string[] id_list, string[] report, int k)
{
var reportMap = new Dictionary<string, HashSet<string>>();
var reportCount = new Dictionary<string, int>();
foreach (var id in id_list)
{
reportMap[id] = new HashSet<string>();
reportCount[id] = 0;
}
// 유저별 신고 처리
foreach (var r in report)
{
var parts = r.Split(' ');
var reporter = parts[0];
var target = parts[1];
if (reportMap[reporter].Add(target))
{
reportCount[target]++;
}
}
// 메일 발송 횟수 계산
var answer = new int[id_list.Length];
for (int i = 0; i < id_list.Length; i++)
{
var reporter = id_list[i];
foreach (var reported in reportMap[reporter])
{
if (reportCount[reported] >= k)
{
answer[i]++;
}
}
}
return answer;
}
🔄 정리
HashSet을 사용해서 깔끔하게 풀 수 있는 문제라서 그냥 Dictionary<string, List<string>> 보다 Dictionary<string, HashSet<string>>을 써볼 수 있으면 좋겠다.
'Coding Test > Programmers' 카테고리의 다른 글
[Lv.1] 나머지가 1이 되는 수 찾기 [프로그래머스_코딩테스트] [수학, 완전탐색] [15분] (0) | 2025.06.17 |
---|---|
[Lv.0] 문자열 정렬하기 (1) [프로그래머스_코딩테스트] [문자열, 정렬] [15분] (0) | 2025.06.16 |
[Lv.1] 둘만의 암호 [프로그래머스_코딩테스트] [문자열, 구현] [30분] (0) | 2025.06.15 |
[Lv.1] 로또의 최고 순위와 최저 순위 [프로그래머스_코딩테스트] [수학, 시뮬레이션] [30분] [2021 Dev-Matching: 웹 백엔드 개발자(상반기)] (2) | 2025.06.14 |
[Lv.1] 문자열 다루기 기본 [프로그래머스_코딩테스트] [문자열, 조건문] [20분] (0) | 2025.06.13 |