Shiny Sky Blue Star

카테고리 없음

JAVA 프로그래머스 Lv.3 베스트앨범

gamja00 2024. 12. 24. 19:51

 

https://school.programmers.co.kr/learn/courses/30/lessons/42579

 


문제

  1. 입력으로 1차원 문자열 배열 genres과 1차원 문자열 배열 plays ( 1 <= genres.length, plays.length <= 10000, genres.length ==  plays.length,  1 <= 장르의 종류 < 100 )이 입력으로 들어옴.
  2. 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 출력한다.
  3. 노래는 고유 번호로 구분한다.
  4. 노래를 수록하는 기준은 속한 노래가 많이 재생된 장르 먼저, 장르 내에서 많이 재생된 노래 먼저, 장르 내에서 재생 횟수가 탕을 시에는 고유 번호가 낮은 노래 먼저 수록한다.

 

 

초기 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static class playsNumber {
        Integer p;
        Integer n;

        public playsNumber(Integer plays, Integer number) {
            p = plays;
            n = number;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String[] genres = {"classic", "pop", "classic", "classic", "pop"};
        Integer[] plays = {500, 600, 150, 800, 2500};


        HashSet<String> type = new HashSet<>(Arrays.asList(genres));
        Iterator<String> ite = type.iterator();

        HashMap<String, ArrayList<playsNumber>> list = new HashMap<>();

        int[] answer = new int[type.size() * 2];

        for (int i = 0; i < genres.length; i++) {
            if (!list.containsKey(genres[i])) {
                ArrayList<playsNumber> num = new ArrayList<>();
                num.add(new playsNumber(plays[i], i));
                list.put(genres[i], num);
            } else {
                ArrayList<playsNumber> temp = list.get(genres[i]);
                temp.add(new playsNumber(plays[i], i));
                list.put(genres[i], temp);
            }
        }

        for (int i = 0; i < list.size(); i++) {
            ArrayList<playsNumber> temp = list.get(genres[i]);
            temp.sort(Collections.reverseOrder());
            list.put(genres[i], temp);
        }

        Integer[] temp = new Integer[list.size()];
        String[][] count = new String[type.size()][2];

        for (int i = 0; i < type.size(); i++) {
            String typeName = ite.next();

            count[i][0] = typeName;

            ArrayList<playsNumber> num = list.get(typeName);
            temp[i] = num.getFirst().p;
        }

        Arrays.sort(temp, Collections.reverseOrder());

        ite = type.iterator();
        int resultCount = 0;

        for (int i = 0; i < list.size(); i++) {
            boolean flag = true;
            while (flag) {
                String typeName = ite.next();
                ArrayList<playsNumber> num = list.get(typeName);
                if (Objects.equals(temp[i], num.getFirst().p)) {
                    for (int j = 0; j < list.size(); j++) {
                        if (Objects.equals(typeName, count[j][0])) {
                            if(num.size()==1){
                                answer[resultCount++] = num.getFirst().n;
                                count[j][1] = String.valueOf(1);
                                flag = false;
                            }
                            else{
                                answer[resultCount++] = num.getFirst().n;
                                answer[resultCount++] = num.get(1).n;
                                count[j][1] = String.valueOf(2);
                                flag = false;
                            }
                        }
                    }
                }
            }

        }

        System.out.println(Arrays.toString(answer));
    }
}

 

예전에 만든 코드라서 기억은 잘 안 나지만 설명을 대충 해보자면

장르를 hashset으로 중복을 없게 만들고,

hashmap으로 장르 이름, 재생 횟수와 고유 번호를 구조체로 만들어서 테이블로 정리하고 싶었던 것 같다.

지금 보니 코드가 굉장히 복잡하다.

아마도 각 장르별로 두 개의 곡을 골라 놓고 장르 순서대로 출력하는 방법인 것 같다.

 

또 다른 초기 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    public static class song {
        int number;
        String genre;
        int play;

        public song(int number, String genre, int play) {
            this.number = number;
            this.genre = genre;
            this.play = play;
        }

        public int getPlay() {
            return this.play;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int[] answer = {};

        String[] genres = {"classic", "pop", "classic", "classic", "pop"};
        int[] plays = {500, 600, 150, 800, 2500};

        HashMap<String, Integer> playSum = new HashMap<String, Integer>();

        for (int i = 0; i < genres.length; i++) {
            if(playSum.containsKey(genres[i])){
                playSum.replace(genres[i], playSum.get(genres[i])+plays[i]);
            }else{
                playSum.put(genres[i], plays[i]);
            }
        }

        System.out.println(playSum);

        HashSet<String> type = new HashSet<>(Arrays.asList(genres));
        Iterator<String> ite = type.iterator();

        String[][] genreCount = new String[type.size()][2];

        for (int i = 0; i < type.size(); i++){
            genreCount[i][0] = ite.next();
        }
        
        

    }
}

모든 항목을 모아서 구조체에 넣은 후 사용하는 방법인 것 같다.

hashmap을 이용하여 장르와 장르별 재생 횟수를 정리했다.

이 뒤엔 없지만 아마 구조체를 이용한 리스트와 hashmap을 이용해 장르를 대조하여 결과를 출력하려고 했던 것 같다.

 

최종 코드

import java.util.*;
class Solution {
    public int[] solution(String[] genres, int[] plays) {
        int[] answer = {};
        
        ArrayList<Integer> answerTemp = new ArrayList<>();

        HashMap<String, Integer> genresList = new HashMap<>();

        for (int i = 0; i < genres.length; i++) {
            if (genresList.containsKey(genres[i])) {
                genresList.replace(genres[i], genresList.get(genres[i]) + plays[i]);
            } else {
                genresList.put(genres[i], plays[i]);
            }
        }

        HashMap<String, HashMap<Integer, Integer>> list = new HashMap<>();

        for (int i = 0; i < genres.length; i++) {
            if (list.containsKey(genres[i])) {
                list.get(genres[i]).put(i, plays[i]);

            } else {
                HashMap<Integer, Integer> temp = new HashMap<>();
                temp.put(i, plays[i]);
                list.put(genres[i], temp);
            }
        }

        ArrayList<String> keySet = new ArrayList<>(genresList.keySet());
        Collections.sort(keySet, (s1, s2) -> genresList.get(s2) - (genresList.get(s1)));

        for (int i = 0; i < genresList.size(); i++) {
            HashMap<Integer, Integer> temp = list.get(keySet.get(i));
            ArrayList<Integer> musicTemp = new ArrayList<>(temp.keySet());
            Collections.sort(musicTemp, (s1, s2) -> temp.get(s2) - (temp.get(s1)));

            if (musicTemp.size() >= 2) {
                answerTemp.add(musicTemp.get(0));
                answerTemp.add(musicTemp.get(1));
            } else {
                answerTemp.add(musicTemp.get(0));
            }
        }

        answer = answerTemp.stream().mapToInt(i -> i).toArray();
        
        return answer;
    }
}

전부 갈아엎고 새로 시작했다.

구조는 전부 내가 만든 것에서 응용해서 구조를 짰는데

그 구조대로 코드 짜는 것이 어려워서 블로그를 참조했다.

 

먼저 hashmap을 이용하여 장르와 장르별 재생 횟수를 중복 없이 저장하도록 했다.

 

이후 hashmap을 이용하여 

	HashMap<String, HashMap<Integer, Integer>> list = new HashMap<>();

        for (int i = 0; i < genres.length; i++) {
            if (list.containsKey(genres[i])) {
                list.get(genres[i]).put(i, plays[i]);

            } else {
                HashMap<Integer, Integer> temp = new HashMap<>();
                temp.put(i, plays[i]);
                list.put(genres[i], temp);
            }
        }

장르별로 고유 번호와 재생 횟수를 저장하도록 했다.

원래는 구조체를 이용하여 저장했는데 hashmap을 이용하여 저장해서 더 빠르게 되라고 해봤다.

 

ArrayList<String> keySet = new ArrayList<>(genresList.keySet());
Collections.sort(keySet, (s1, s2) -> genresList.get(s2) - (genresList.get(s1)));

이 부분을 특히 블로그를 많이 참조했다.

[참조] https://velog.io/@ewoo97/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%95%B4%EC%8B%9C-%EB%B2%A0%EC%8A%A4%ED%8A%B8-%EC%95%A8%EB%B2%94-Java

 

hashmap을 정렬할 방법을 모르겠어서 찾아봤다.

.keyset이라는 함수를 처음 사용해봤다.

이 코드는 keyset이라는 함수를 이용하여 hashmap의 key들을 뽑아 arraylist에 저장한 후에 다시 내림차순 정렬하는 코드이다.

정렬할 때에는 hashmap에서 해당 key에 대한 값을 뽑아 비교하여 정렬에 이용하는 방법이다.

 

	for (int i = 0; i < genresList.size(); i++) {
            HashMap<Integer, Integer> temp = list.get(keySet.get(i));
            ArrayList<Integer> musicTemp = new ArrayList<>(temp.keySet());
            Collections.sort(musicTemp, (s1, s2) -> temp.get(s2) - (temp.get(s1)));

            if (musicTemp.size() >= 2) {
                answerTemp.add(musicTemp.get(0));
                answerTemp.add(musicTemp.get(1));
            } else {
                answerTemp.add(musicTemp.get(0));
            }
        }

이 코드는 장르별로 고유 번호와 재생 횟수를 저장한 hashmap을 이용해 장르를 순서대로 정렬한 arraylist인 keyset 배열을 이용하여 각 장르별로 2곡씩 정답 배열에 저장한 코드이다.

여기도 마찬가지로 hashmap을 장르별로 저장했기 때문에 장르가 정렬된 keyset 배열 순서대로 기존에 hashmap에 들어있던 재생 횟수와 고유번호를 담은 부분을 꺼내어 이용한다.

이후 keyset 함수를 이용하여 arraylist에 저장하고 hashmap에 저장된 재생 횟수대로 내림차순 정렬하도록 했다.

 

이후 저장 시에는 장르별로 최대 2곡이기 때문에 1곡일 때는 가장 재생 횟수가 많은 곡만 수록하고 2곡 이상일 때에는 가장 많은 2곡을 저장하도록 했다.

 

answer = answerTemp.stream().mapToInt(i -> i).toArray();

이 부분은 정답이 적힌 arraylist를 int 배열에 넣는 코드이다.

가끔 사용하기 때문에 잘 외워지지 않아 블로그를 참조하였다.

이 코드 정도는 외워두는 것도 나쁘지 않을 것 같다.

 

[참조] https://velog.io/@deannn/Java-int%ED%98%95-ArrayList-%EB%B0%B0%EC%97%B4-EB%B3%80%ED%99%98