/////////
Search
🎇

신고 결과 받기_(+조금의 시간 복잡도)

레벨 1이지만 사악한 문제..(정답률 30퍼대)

배열로 풀기

이전에 풀었던 문제인데 사실 그때는 해시가 뭔지도 몰라서 그냥 배열로 풀었다.. 카카오 기출인만큼 1레벨인데도 어렵고 코드가 긴느낌,, (다른 분들 파이썬 코드보니 자바라 그런것 같기도;)
//해시 아닌것으로 풂 class User{ String username; int index=0; } class Solution { public int[] solution(String[] id_list, String[] report, int k) { int [][] list=new int[id_list.length][id_list.length+1]; User[] user=new User[id_list.length]; for(int i=0;i<id_list.length;i++){ //...1) 1000회 user[i]=new User(); user[i].username=id_list[i]; } for(int i=0;i<report.length;i++){ //...2) 20만회 String[] splited=report[i].split(" "); for(int j=0;j<id_list.length;j++){ //...3) 1000회 int idx=0; boolean bool=false; //신고한 유저 이름 검색 if(user[j].username.equals(splited[0])){ idx=j; bool=true; //신고당한 유저 이름 검색 for(int p=0;p<id_list.length;p++){ //...4) 1000회 if(user[p].username.equals(splited[1])){ if(list[idx][p]==0){ //같은유저가 같은 유저를 신고한 경우가 아닐경우 list[idx][p]=1; list[p][id_list.length]++; } break; } } } if(bool){ break; } } } int[] answer = new int[id_list.length]; for(int i=0;i<id_list.length;i++){ //...5) 1000회 if(list[i][id_list.length]>=k){ for(int j=0;j<id_list.length;j++){ //...6) 1000회 if(list[j][i]==1){ answer[j]++; } } } } return answer; } }
Java
복사
지금 다시보니까 사실상 해시 맵을 배열로 구현한 느낌이다.
2차원 배열을 선언하고 각 행마다 id를 저장한 뒤 해당 행에 해당 id가 신고한 유저의 id를 넣는 방식.
시간복잡도 제한을 어떻게 통과했는지 모르겠다. (간당간당 했을것 같다)
1초에 1억번 연산(10^9)이 가능하다고 생각하고 설계해야한다.
위의 코드에서 id_list의 길이가 최대 1,000, report의 길이가 최대 200,000이다.

시간 복잡도: 10^3 + 2*10^5*10^3*10^3 + 10^3*10^3 =약 10^11

(10초 제한인데 어떻게 통과한걸까^^;;)
N의 제한에 따른 시간 복잡도를 고려한 알고리즘 설계

결국 이 문제는 해시를 이용해야 시간제한을 통과할 수 있는 문제다!

해시 맵은 get과 put 모두 시간복잡도가 단 O(1)이다.

해시로 풀기

import java.util.ArrayList; import java.util.HashMap; class Solution { public static int[] solution(String[] id_list, String[] report, int k) { HashMap<String, Integer> hm = new HashMap<>(); //"신고한사람 신고받은사람" , 있는지 없는지(null, 1) HashMap<String ,Integer> hmCount = new HashMap<>(); // 신고 받은 사람, 신고받은 횟수(중복제외) HashMap<String ,Integer> ans = new HashMap<>(); // 신고한 사람- 신고 메일 받은 횟수 for(int i=0;i<report.length;i++){ //...1) 10^5 //신고 저장 String[] splitted = report[i].split(" "); if(hm.get(report[i])==null){ //한 유저가 특정 유저 최초 신고시에만 신고 저장 hm.put(report[i],1); if(hmCount.get(splitted[1])==null){ hmCount.put(splitted[1],1); continue; } hmCount.put(splitted[1],hmCount.get(splitted[1])+1); } } for (String s : hmCount.keySet()) { //...2) 최대 10^3 if(hmCount.get(s)>=k){ //신고 당한 횟수가 k인 회원(s)을 찾기 for(int i=0;i<id_list.length;i++){ //...3) 10^3 //회원s를 신고한 회원 찾기 String keyString = id_list[i]+" "+s; if(hm.get(keyString)!=null){ //회원 신고 메세지를 몇개 받는지를 저장 if(ans.get(id_list[i])==null){ ans.put(id_list[i],1); } else{ ans.put(id_list[i],ans.get(id_list[i])+1); } } } } } //전체 회원의 받은 메일 개수를 저장하는 리스트 ArrayList<Integer> ansList = new ArrayList<>(); for(int i=0;i<id_list.length;i++){ //...4) 10^3 if(ans.get(id_list[i])!=null) ansList.add(ans.get(id_list[i])); else{ ansList.add(0); } } //리스트를 다시 배열로 저장해서 리턴 int[] ansArr = new int[ansList.size()]; int size = 0; for(Integer integer:ansList){ //...5) 10^3 ansArr[size++] = integer; } return ansArr; } }
Java
복사

시간복잡도를 약 10^5 정도로 대폭 감소시켰다.