티스토리 뷰

반응형

프로그래머스 알고리즘 - 베스트 앨범

프로그래머스 베스트 앨범 문제 링크

문제 설명과 제한사항을 빠짐없이 이해해야 실수 없이 코딩이 가능합니다. 장르(genre)를 먼저 나열 하는데 이에 기준이 장르의 속한 모든 노래들의 재생횟수(plays)입니다. 그러나 장르 내에서 노래를 정렬 할 때는, 많이 재생된 최상위 노래를 최대 2개까지 보여줍니다. 함정에 빠질 수도 있는 것이 최대2개입니다. 1개만 있을 경우 1개만 나와야하며, 노래들은 이름 없이 인덱스로 구분하게 됩니다.

문제풀이(java)

장르(genre)와 노래(song)에 해당 하는 클래스를 만들어서 해당 정보들을 기입하고, 내림차순 정렬시에 Collections.sort를 사용하는 방법을 선택했습니다. 클래스를 둘로 나누어서 풀어보니 한 장르의 속한 모든 노래들의 재생횟수를 구하기에 좀 더 수월 했습니다.


  1. Song(노래) 클래스를 만듭니다. Song을 구분하기 위한 index재생 횟수(playCount)를 필드로 가지게 됩니다. 그리고 재생 횟수를 기준으로 오름차순으로 정렬을 하기 위해서 Comparable 인터페이스를 구현합니다.
  2. class Song implements Comparable<Song>{
        private int index;
        private int playCount;
        . . . 
    
        @Override
        public int compareTo(Song o) {
            return o.playCount - this.playCount;
        }
    }
    
  3. Genre(장르) 클래스를 만듭니다. Genre클래스는 고유의 이름(name)Song들을 담고 있는 List, 그리고 속한 모든 노래들의 재생 횟수를 더한 총 재생횟수(totalCount)를 필드로 가지게 됩니다. 그리고 총 재생횟수를 기준으로 오름차순 정렬을 하기 위해서 Comparable 인터페이스를 구현합니다.
  4. class Genre implements Comparable<Genre>{
        private String name;
        private List<Song> songs;
        private int totalCount;
        . . .
    
        @Override
        public int compareTo(Genre o) {
            return o.totalCount - this.totalCount;
        }
    }
    
  5. Genre(장르) 객체는 고유한 이름을 하나만 가져야 합니다. 그러므로 equals와 hashCode 메소드를 오버라이딩 해줍니다. equals의 기준이 되는 필드는 name 하나면 충분합니다.
  6. class Genre implements Comparable<Genre>{
        . . . 
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Genre genre = (Genre) o;
            return name != null ? name.equals(genre.name) : genre.name == null;
        }
    
        @Override
        public int hashCode() {
            return name != null ? name.hashCode() : 0;
        }
    }
  7. 입력값을 이용하여서 Genre와 Song 객체를 만들고 담아줍니다. 같은 이름의 장르가 여러개 생성되지 않도록 주의합니다.
  8. private List<Genre> setGenresAndSongs(String[] genres, int[] plays) {
        List<Genre> genreList = new ArrayList<>();
        for (int i = 0; i<genres.length; i++) {
            Genre genre1 = new Genre(genres[i]);
            if (!genreList.contains(genre1)) {
                genreList.add(genre1);
            }
            for (Genre genre : genreList) {
                if (genre.getName().equals(genres[i])) {
                    genre.addSong(new Song(i, plays[i]));
                }
            }
        }
        return genreList;
    }
    }
  9. 각 Genre 객체들이 담고 있는 List<Song>을 Collecttions.sort() 메소드를 통해서 오름차순으로 정렬합니다.
  10. Collections.sort(songs);
    
  11. 각 Genre 객체들의 총 재생횟수를 구하고, Genre들을  Collecttions.sort() 메소드를 통해서 오름차순으로 정렬합니다.
  12. void calcTotalCount() {
        for (Song song : songs) {
            totalCount += song.getPlayCount();
        }
    }
    Collections.sort(genreList);
    
  13. 이제 정렬을 다 된 상태이니 첫번째 Genre부터 최대 2곡씩 해당하는 노래의 인덱스를 출력합니다.
  14. List<Integer> answerList = new ArrayList<>();
    for (Genre genre : genreList) {
        answerList.add(genre.getSong(0).getIndex());
        if (genre.getSongs().size() > 1) {
            answerList.add(genre.getSong(1).getIndex());
        }
    }
    

배운점

  • equals 와 hashCode 메소드를 적절하게 사용하였다. equals 기준이 되는 필드가 무엇인지 잘 생각해야 한다.
  • 문제에 대한 이해를 완전히 하지않아 totalCount를 모든 노래가 아닌, 상위 2곡만으로 구해서 디버깅 하는데 애를 먹었다. 이런 실수는 하지 않도록 항상 주의해야 한다. 제한 시간이 있었다면 시간 잡아 먹는 도둑이다! 이런 실수로 틀린다면 너무 억울하지 않은가~ 항상 문제를 확실히 이해하고 메모하자. 급하게 하면 결국 배로 시간을 쓰게 된다.

문제 풀이 코드 Github 주소

반응형
댓글