2025-10-19 학습 기록

랏 뜨·2025년 10월 19일

📑 세부 학습 내용


📅 스케쥴

  • 5시간 30분 독서 + 궁금한 개념 조사 및 학습 + 2시간 코딩테스트 및 풀이 리뷰
  • 7시간 30분

🧷 학습 시간 인증


📖 도서 정독 및 실습

실전 레디스 : 기초, 실전, 고급 단계별로 배우는 레디스 핵심 가이드

  • 캐싱 등 RDB 의 보조 역할을 해줄 NoSQL 중 가장 범용적이고 유지보수가 잘 진행 중인 Redis 의 구조부터 기초, 심화 내용, 사용법 등을 확실하게 이해하여, 이후의 프로그래밍에 있어 자신 있고 근거 있게 레디스를 채택하고 사용할 수 있는 개발자를 목표로 독서 시작
  • 8. 레디스 클러스터 (p.482) ~ 8.5 레디스 클러스터 관련 명령어 (p.503)
    • 8.6 레디스 클러스터 설치 방법 - 실습 진행 중
    • p.512까지 진행
  • 도서 내 모든 내용 이해 및 실습 완료
    • 궁금한 부분은 따로 조사 후 학습

✏️ 코딩 테스트

⭕ 문제 풀이

class Solution {

    int n;
    static final int SCORE_IDX = 4;
    Map<String, List<Integer>> map = new HashMap<>();

    public int[] solution(String[] info, String[] query) {
        n = query.length;
        int[] results = new int[n];
        for (String str : info) {
            String[] bits = str.split(" ");
            dfs(bits, "", 0, Integer.parseInt(bits[SCORE_IDX]));
        }

        for (List<Integer> list : map.values()) {
            list.sort(Comparator.reverseOrder());
        }

        int idx = 0;
        for (String queryStr : query) {
            String[] andSplit = queryStr.replaceAll(" and ", " ").split(" ");
            String[] keyQueries = new String[SCORE_IDX];
            System.arraycopy(andSplit, 0, keyQueries, 0, SCORE_IDX);
            String keyQuery = String.join("", keyQueries);
            List<Integer> keyList = map.getOrDefault(keyQuery, new ArrayList<>());
            results[idx++] = binarySearch(keyList, Integer.parseInt(andSplit[SCORE_IDX]));
        }

        return results;
    }

    private void dfs(String[] bits, String key, int depth, int score) {
        if (depth == SCORE_IDX) {
            map.computeIfAbsent(key, k -> new ArrayList<>()).add(score);
            return;
        }

        dfs(bits, key + bits[depth], depth + 1, score);
        dfs(bits, key + "-", depth + 1, score);
    }

    private int binarySearch(List<Integer> list, int score) {
        int start = 0;
        int end = list.size();
        while (start < end) {
            int mid = (start + end) / 2;
            if (list.get(mid) >= score) {
                start = mid + 1;
            } else {
                end = mid;
            }
        }

        return start;
    }
}
  • 풀이 실패
    • Map<String, Map<String ...>> 구조로 풀어보려 했으나, 맵 안에 맵 안에 맵 안에... 구조가 되어버려서 포기
    • Node 클래스를 만들어서 List<Node> 를 내부에 담고 풀어보려 했으나 생각보다 복잡해져서 포기
    • 아이디어 및 풀이 코드 참고하여 이해 후 스스로 다시 풀이
  • info 배열 각 요소를 문제의 의도에 맞춰 split 한 후, - 일 때와 info.split 요소일 때를 나눠서 한 줄의 key 로 쭉 연결
  • 점수 처리 구간이 되면 해당 점수를 기존 Map<String, List<Integer>> map 의 리스트에 추가
  • map.values()내림차순으로 정렬
    • 이진 탐색을 이용해 조건에 맞지 않는 최소 인덱스를 구하기 위함
  • query 배열을 조건에 맞게 자른 후 info 에서 key 로 연결하던 것 처럼 요소를 key 로 쭉 연결
    • map.getOrDefault() 를 통해 키에 맞는 리스트 획득
      • 없으면 빈 리스트 반환
    • 획득한 점수 외 조건에 맞는 리스트조건 점수이진 탐색을 이용하여 값 획득 후 정답 배열에 추가
  • 최종 시간복잡도 : O((N logN) + (Q logN))
    • map.values() 정렬 : O(N * logN)
      • Ninfo.length
      • 조합이 2⁴개이므로 map.values()리스트의 원소 개수 총합16 * N, 결국 O(N)에 수렴
      • 정렬이므로 O(N * logN)
    • 이진 탐색 : O(Q * logN)
      • Qquery.length
      • list 는 결국 O(N) 에 수렴하므로, 리스트 하나의 이지탐색은 O(logN)
    • 최종 시간복잡도 : O((N logN) + (Q logN))

💡 어려웠던 것 || 알게 된 것


레디스 마스터-레플리카 레플리케이션

profile
기록

0개의 댓글