갓생사는 김초원의 개발 블로그
chocho_log
갓생사는 김초원의 개발 블로그
전체 방문자
오늘
어제
  • 분류 전체보기 (77)
    • 개발 (22)
      • Spring (4)
      • Java (3)
      • Database (2)
      • Elasticsearch (3)
      • ETC (3)
      • JPA (3)
      • 이슈 (1)
    • 코딩 테스트 (43)
      • 프로그래머스 (23)
      • 백준 (12)
      • TIP (8)
    • 자료구조 (2)
    • 알고리즘 (4)
    • 잡생각 (0)
    • 경험 (5)
      • AWS re:Invent 2024 (5)

블로그 메뉴

    공지사항

    인기 글

    태그

    • 디자인패턴 #SOLID 원칙
    • war
    • Spring Boot Embedded Tomcat
    • querydsl
    • jar
    • jpa
    • Lazy Loading
    • 지연로딩

    최근 댓글

    최근 글

    갓생사는 김초원의 개발 블로그

    chocho_log

    코딩 테스트/프로그래머스

    [프로그래머스][Level4] 자동완성 - JAVA

    2021. 7. 24. 18:51

    [문제]

    • 2018 KAKAO BLIND RECRUITMENT

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

     

    코딩테스트 연습 - [3차] 자동완성

    자동완성 포털 다음에서 검색어 자동완성 기능을 넣고 싶은 라이언은 한 번 입력된 문자열을 학습해서 다음 입력 때 활용하고 싶어 졌다. 예를 들어, go 가 한 번 입력되었다면, 다음 사용자는 g

    programmers.co.kr

     

    [풀이]

    단어 검색 관련 문제는 Trie 트리 자료구조를 이용하여 풀어야 한다. 

    (단어 검색, 자동 완성 등등 --> 자동으로 "Trie"가 떠올라야함)

     

    <Trie자료구조 JAVA 코드>

    Trie 구현코드를 처음부터 끝까지 작성하기는 쉽지 않다.

    개인적으로 이런 문제를 풀 때는 팀노트나 블로그에 기록해두고 그때 그때 찾아서 응용하는 편이다.

    더보기
    package com.algorithm.tree;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class TrieTree {
    
        static class TrieNode {
            private Map<Character, TrieNode> childNodes = new HashMap<>();
            private boolean isLastChar;
        }
    
        static class Trie {
            TrieNode rootNode;
    
            public Trie() {
                rootNode = new TrieNode();
            }
    
            void insert(String word) {
                TrieNode thisNode = this.rootNode;
    
                for (int i = 0; i < word.length(); i++) {
                    thisNode = thisNode.childNodes.computeIfAbsent(word.charAt(i), c -> new TrieNode());
                }
                thisNode.isLastChar = true;
            }
    
            boolean contains(String word) {
                TrieNode thisNode = this.rootNode;
    
                for (int i = 0; i < word.length(); i++) {
                    char character = word.charAt(i);
    
                    TrieNode node = thisNode.childNodes.get(character);
    
                    if (node == null) {
                        return false;
                    }
    
                    thisNode = node;
                }
                return thisNode.isLastChar;
            }
    
            void delete(String word) {
                delete(this.rootNode, word, 0);
            }
    
            void delete(TrieNode thisNode, String word, int index) {
                char character = word.charAt(index);
    
                if (!thisNode.childNodes.containsKey(character)) {
                    throw new Error("There is no [" + word + "] in this Trie.");
                }
    
                TrieNode childNode = thisNode.childNodes.get(character);
                index++;
    
                if (index == word.length()) {
                    if (!childNode.isLastChar) {
                        throw new Error("There is no [" + word + "] in this Trie.");
                    }
                    childNode.isLastChar = false;
    
                    if (childNode.childNodes.isEmpty()) {
                        thisNode.childNodes.remove(character);
                    }
                } else {
                    delete(childNode, word, index);
    
                    if (!childNode.isLastChar && childNode.childNodes.isEmpty()) {
                        thisNode.childNodes.remove(character);
                    }
                }
            }
        }
    }

     

    <접근 방법>

    루트 노드부터 시작하여 자식 노드로 내려가며 문자 하나하나씩을 순차적으로 탐색한다. 

    자식노드로 내려가면서 카운팅한다.(문자 입력 개수 카운팅)

    이 문자가 현재 검색하려는 단어에만 들어가는지, 이외에 다른 단어에도 들어가는지를 알아내면 된다. 

    1. 현재 검색하려는 단어에만 포함되는 문자라면? -> 문자 입력 개수 리턴

    2. 현재 검색하려는 단어 이외에 다른 단어들에도 포함된다. -> 자식노드로 더 내려감

     static class TrieNode {
            private Map<Character, TrieNode> childNodes = new HashMap<>();
            private int cnt; // 해당 문자가 몇개의 단어들에 포함되는지 카운트
    }

     

     

     

    [코드]

    package com.algorithm.kakaoTest.three;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 자동 완성
     * 소요시간: 57분 38초
     */
    public class Test03 {
        public static void main(String[] args) {
            String[] words =// {"go", "gone", "guild"};
                    //{"word", "war", "warrior", "world"};
                    {"abc", "def", "ghi", "jklm"};
            int answer = solution(words);
            System.out.println(answer);
        }
    
        static class TrieNode {
            private Map<Character, TrieNode> childNodes = new HashMap<>();
            private int cnt;
        }
    
        static class Trie {
            TrieNode rootNode;
    
            public Trie() {
                rootNode = new TrieNode();
            }
    
            void insert(String word) {
                TrieNode thisNode = this.rootNode;
    
                for (int i = 0; i < word.length(); i++) {
                    thisNode = thisNode.childNodes.computeIfAbsent(word.charAt(i), c -> new TrieNode());
                    thisNode.cnt++;
                }
            }
    
            int getInputCounts(String word) {
                int count = 0;
                TrieNode thisNode = this.rootNode;
    
                for (int i = 0; i < word.length(); i++) {
                    char character = word.charAt(i);
                    TrieNode node = thisNode.childNodes.get(character);
                    count++;
    
                    if (node.cnt == 1) {
                        return count;
                    }
                    thisNode = node;
                }
                return count;
            }
        }
    
        public static int solution(String[] words) {
            int answer = 0;
    
            // Trie 트리 생성
            Trie trie = new Trie();
            for (String word : words) {
                trie.insert(word);
            }
    
            for (String word : words) {
                answer += trie.getInputCounts(word);
            }
            return answer;
        }
    }

     

    참고
    https://the-dev.tistory.com/2
    https://the-dev.tistory.com/3

    '코딩 테스트 > 프로그래머스' 카테고리의 다른 글

    [프로그래머스][Level2][JAVA] [1차]뉴스 클러스터링  (0) 2021.08.20
    [프로그래머스] 무지의 먹방 라이브 - JAVA  (0) 2021.08.02
    [프로그래머스][LEVEL2] 캐시 - JAVA  (0) 2021.07.22
    [프로그래머스] [Level2] 프렌즈4블록 - JAVA  (0) 2021.07.14
    [프로그래머스][Level3] 자물쇠와 열쇠 - JAVA  (1) 2021.05.24
      '코딩 테스트/프로그래머스' 카테고리의 다른 글
      • [프로그래머스][Level2][JAVA] [1차]뉴스 클러스터링
      • [프로그래머스] 무지의 먹방 라이브 - JAVA
      • [프로그래머스][LEVEL2] 캐시 - JAVA
      • [프로그래머스] [Level2] 프렌즈4블록 - JAVA
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그 github: https://github.com/kimchowon

      티스토리툴바