Algorithm/이코테

30.가사 검색

마닐라 2022. 1. 11. 16:11

📍 문제 설명

https://programmers.co.kr/learn/courses/30/lessons/60060

 

코딩테스트 연습 - 가사 검색

 

programmers.co.kr

 

💡 접근

??로 해당하는 부분을 aa, zz로 변경시켜서 그 사이에 있는 문자열들을 더해주면 되는 문제였다.

?로 시작하는 경우도 있기 때문에 뒤집힌 문자열도 따로 리스트에 담아두어서 '?'의 위치에 따라

다른 리스트들을 사용하여 구했음

 

👩‍💻 코드

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner kb = new Scanner(System.in);
        String[] words = {"frodo", "front", "frost", "frozen", "frame", "kakao"};
        String[] queries = {"fro??", "????o", "fr???", "fro???", "pro?"};

        solution(words, queries);
    }

    private static int[] solution(String[] words, String[] queries) {
        ArrayList<Integer> ans = new ArrayList<Integer>();

        //모든 단어들을 길이마다 나누어서 저장
        ArrayList<ArrayList<String>> arr = new ArrayList<>();
        //모든 단어들을 길이마다 나누어서 뒤집어 저장
        ArrayList<ArrayList<String>> reversedArr = new ArrayList<>();

        // 단어의 길이는 10,000까지 가능
        for (int i = 0; i < 10001; i++) {
            arr.add(new ArrayList<String>());
            reversedArr.add(new ArrayList<String>());
        }

        // 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            arr.get(word.length()).add(word); // 단어를 삽입
            word = (new StringBuffer(word)).reverse().toString();
            reversedArr.get(word.length()).add(word); // 단어를 뒤집어서 삽입
        }

        // 이진 탐색을 수행하기 위해 각 단어 리스트 정렬 수행
        for (int i = 0; i < 10001; i++) {
            Collections.sort(arr.get(i));
            Collections.sort(reversedArr.get(i));
        }
        System.out.println(arr);
        System.out.println(reversedArr);

        // 쿼리를 하나씩 확인하며 처리
        for (int i = 0; i < queries.length; i++) {
            String q = queries[i];
            int res = 0;
            if (q.charAt(0) != '?') { // 접미사에 와일드 카드가 붙은 경우
                res = countByRange(arr.get(q.length()), q.replaceAll("\\?", "a"), q.replaceAll("\\?", "z"));
            }
            else { // 접두사에 와일드 카드가 붙은 경우
                q = (new StringBuffer(q)).reverse().toString();
                res = countByRange(reversedArr.get(q.length()), q.replaceAll("\\?", "a"), q.replaceAll("\\?", "z"));
            }
            // 검색된 단어의 개수를 저장
            ans.add(res);
        }

        // 배열로 바꾸어 반환
        int[] answer = new int[ans.size()];
        for (int i = 0; i < ans.size(); i++) {
            answer[i] = ans.get(i);
        }
        return answer;
    }

    // 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
    public static int countByRange(ArrayList<String> arr, String leftValue, String rightValue) {
        System.out.println("시작 문자열 : " + leftValue);
        System.out.println("끝 문자열 : " + rightValue);
        System.out.println("탐색할 문자열들 : " + arr);
        // 유의: lowerBound와 upperBound는 end 변수의 값을 배열의 길이로 설정
        int rightIndex = upperBound(arr, rightValue, 0, arr.size());
        int leftIndex = lowerBound(arr, leftValue, 0, arr.size());
        System.out.println("rightIndex : " + rightIndex);
        System.out.println("leftIndex : " + leftIndex);
        System.out.println(rightIndex-leftIndex);
        return rightIndex - leftIndex;
    }

    public static int lowerBound(ArrayList<String> arr, String target, int start, int end) {
        while (start < end) {
            int mid = (start + end) / 2;
            // arr[mid]가 target보다 사전순으로 같거나 뒤에 있다면
            if (arr.get(mid).compareTo(target) >= 0) end = mid;
            else start = mid + 1;
        }
        return end;
    }

    public static int upperBound(ArrayList<String> arr, String target, int start, int end) {
        while (start < end) {
            int mid = (start + end) / 2;
            // arr[mid]가 target보다 사전순으로 뒤에 있다면
            if (arr.get(mid).compareTo(target) > 0) end = mid;
            else start = mid + 1;
        }
        return end;
    }

}

'Algorithm > 이코테' 카테고리의 다른 글

32.정수 삼각형  (0) 2022.01.11
31.금광  (0) 2022.01.11
29.공유기 설치  (0) 2022.01.10
28.고정점 찾기  (0) 2022.01.10
27.정렬된 배열에서 특정 수의 개수 구하기  (0) 2022.01.10