1. 문제
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
2. 풀이 과정
1. 재생횟수 총합을 기준으로 높은 순으로 장르 정렬하기
2. 장르안에서도 재생횟수 많은 노래를 알기 위해 모든 노래에 대해서 재생 횟수 기준으로 정렬
3. 장르 순서를 기반으로 해당 장르의 노래 중 재생횟수가 높은 노래 2개씩 배열에 넣기
두 개의 정보를 통해 정답을 구해야한다. 각각의 정보를 뽑아내는 과정은 다음과 같다.
이해를 위해 위의 테스트케이스를 예시로 설명하겠다.
genre:
["classic", "pop", "classic", "classic", "pop"]
play:
[500, 600, 150, 800, 2500]
1. 재생횟수 총합을 기준으로 높은 순으로 장르 정렬하기
1) 장르 - 재생횟수 총합의 관계를 가지는 해시맵에 정보 저장
2) 재생횟수로 내림차순 정렬 한 뒤 장르를 별도의 배열의 저장
2. 장르안에서도 재생횟수 많은 노래를 알기 위해 모든 노래에 대해서 재생 횟수 기준으로 정렬
1) Song 클래스 만들기
다음 3가지를 인스턴스로 가진다.
- id: 노래의 고유번호(배열의 인덱스)
- genre: 노래의 장르(genre[]의 원소)
- play_time: 재생횟수(play[]의 원소)
2) 이 Song클래스 객체 리스트에 저장하기
3) song의 play_time을 기준으로 내림차순 정렬하기
이제 필요한 정보를 가져왔으니 정답만 구하면 된다.
3. 장르 순서를 기반으로 해당 장르의 노래 중 재생횟수가 높은 노래 2개씩 배열에 넣기
1) pop
2) classic
답: [4, 1, 3, 0]
3. 내 코드
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
List<Song> song_list = new ArrayList<>();
HashMap<String, Integer> genre_time = new HashMap<>();
List<Integer> answer = new ArrayList<>();
// 1. 장르 - 재생횟수 관계로 저장 후 재생횟수로 정렬
for(int i = 0; i < genres.length; i++) {
genre_time.put(genres[i], genre_time.getOrDefault(genres[i], 0) + plays[i]);
}
List<Map.Entry<String, Integer>> list = new ArrayList<>(genre_time.entrySet());
list.sort((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()));
// 2. 노래를 리스트에 정렬후 재생횟수로 내림차순 정렬
for(int i = 0; i < genres.length; i++) {
song_list.add(new Song(i, genres[i], plays[i]));
}
song_list.sort((s1, s2) -> Integer.compare(s2.getPlayTime(), s1.getPlayTime()));
// 3. 1,2의 결과를 가지고 장르 순대로 재생횟수가 높은 노래 2개씩 배열에 넣기
for(Map.Entry<String, Integer> entry: list) {
int add_cnt = 0;
for(Song s: song_list) {
if(s.getGenre().equals(entry.getKey())) {
add_cnt++;
answer.add(s.getId());
}
if(add_cnt == 2) {
break;
}
}
}
return answer.stream().mapToInt(i -> i.intValue()).toArray();
}
// 노래 클래스
static class Song {
int id;
String genre;
int play_time;
public Song(int id, String genre, int play_time) {
this.id = id;
this.genre = genre;
this.play_time = play_time;
}
public int getId() {
return this.id;
}
public String getGenre() {
return this.genre;
}
public int getPlayTime() {
return this.play_time;
}
}
}
시간 복잡도
- O(NlogN)
// 3. 1,2의 결과를 가지고 장르 순대로 재생횟수가 높은 노래 2개씩 배열에 넣기
for(Map.Entry<String, Integer> entry: list) {
int add_cnt = 0;
for(Song s: song_list) {
if(s.getGenre().equals(entry.getKey())) {
add_cnt++;
answer.add(s.getId());
}
if(add_cnt == 2) {
break;
}
}
}
언뜻 보면 이 부분이 O(N^2)처럼 보일 수 있다.
하지만 장르의 종류는 100 미만이다.
그러므로 이는 상수로 고려하고 무시할 수 있다.
따라서 내 코드의 시간복잡도는 정렬하는 부분에 대한 O(NlogN)이 시간복잡도가 된다.
문제의 제한사항을 보고 입력의 크기를 잘 파악한 다음 시간복잡도를 고려해 코드를 작성해야 한다.
4. 피드백
- 하나의 데이터 안에 여러 개의 데이터가 존재한다면 클래스를 선언하는 것도 하나의 방법이다.
- 해시 맵을 value를 기준으로 정렬하려면 entrySet() 메서드를 통해 List로 변환한 다음 정렬해야 한다.
'코딩 테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] 메뉴 리뉴얼 (0) | 2024.05.09 |
---|---|
[프로그래머스] 신고 결과 받기 (0) | 2024.05.08 |
[프로그래머스] 오픈채팅 (0) | 2024.05.07 |
[프로그래머스] 할인 행사 (0) | 2024.05.07 |
[프로그래머스] 완주하지 못한 선수 (0) | 2024.05.07 |